c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programming に分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡)

音樂は SoundCloud に公開中です。

考察は現在は主に Scrapbox で公表中です。

Programming は GitHub で開發中です。

node.jsで非同期にdirectory中の全てのfileを読み込む

fs.js
fs.readAllFile(directory, callback)

内部ではQ.deferを使ってるけど、外には漏洩させない構え(ゞ〃l _ l)ゞ
cf. deferred (延期) を自動で連鎖させる (node.js) http://c4se.hatenablog.com/entry/2013/10/05/220501

yieldが出たらgeneratorに書き換えるべきだ。

/**
 * Extends standard FileSystem module.
 *
 * @author ne_Sachirou <utakata.c4se@gmail.com>
 * @license Public Domain
 * @module fs
 */

'use strict';

var fs = require('fs'),
    path = require('path'),
    Q = require('q');

/**
 * Read All files in the directory.
 *
 * @static
 * @param {string} directory or file
 * @param {function(?Error,?Buffer[])} callback
 */
function readAllFiles(directory, callback) {
  readAllFilesRecur(directory, [ ]).
    then(function(files) { callback(null, files); }).
    fail(function(error) { callback(error, null); }).
    done();
}

/*
 * @param {string} directory path
 * @param {Buffer[]} files accumlator
 * @return {Q.defer.promise}
 */
function readAllFilesRecur(directory, files) {
  var deferred = Q.defer();

  files = files || [ ];
  fs.lstat(directory, function(error, stat) {
    if (error) {
      deferred.reject(error);
      return;
    }
    if (stat.isFile()) {
      readFile(directory, files).
        then(deferred.resolve.bind(deferred)).
        done();
    } else if (stat.isDirectory()) {
      readDirectory(directory, files).
        then(deferred.resolve.bind(deferred)).
        done();
    } else {
      deferred.reject(new Error());
    }
  });
  return deferred.promise;
}

function readFile(filename, files) {
  var deferred = Q.defer();

  fs.readFile(filename, function(error, data) {
    if (error) {
      deferred.reject(error);
      return;
    }
    files.push(data);
    deferred.resolve(files);
  });
  return deferred.promise;
}

function readDirectory(directory, files) {
  var deferred = Q.defer();

  fs.readdir(directory, function(error, filenames) {
    var promises = [ ];

    if (error) {
      deferred.reject(error);
      return;
    }
    filenames.
      map(function(filename) { return path.join(directory, filename); }).
      forEach(function(filename) {
        promises.push(readAllFilesRecur(filename, files));
      });
    Q.all(promises).
      then(function(files) { deferred.resolve(files[0]); }).
      fail(deferred.reject.bind(deferred)).
      done();
  });
  return deferred.promise;
}

fs.readAllFiles = readAllFiles;
module.exports = fs;