读取多个目录中的文件,使用Node和Promises将文件名与其数据进行匹配

时间:2015-04-29 15:25:58

标签: javascript node.js promise fs

我有一系列目录。

var directories = ['/dir1', '/dir2'];

我想读取这些目录下的所有文件,最后有一个对象将文件名与其base64 / utf8数据进行匹配。在我的情况下,这些文件是图像。生成的对象可能如下所示:

var result = {
 '/dir1': {
  'file1': 'iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAIAAACx0UUtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWF...',
  'file2': 'iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAIAAACx0UUtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWF...'   
 }
}

我很容易用回调地狱来实现这个,但是当我尝试使用Promises时,我不确定如何传递目录信息,并且知道如何传递then()和map()函数。

在下面的示例中,我使用了Bluebird库:

const Promise = require('bluebird'),
  fs = Promise.promisifyAll(require('fs'));

var getFiles = function (dir) {
      return fs.readdirAsync(dir);
  };

Promise.map(directories, function(directory) {
    return getFiles(directory)
  }).map(function (files) {
    // which directory's files are these?
    return files;
  })

下一步是迭代文件并读取数据。

我不介意回答ES6,Bluebird或Q.

2 个答案:

答案 0 :(得分:2)

使用Bluebird最简单的方法是使用props

function getFiles(paths) { // an array of file/directory paths
    return Promise.props(paths.reduce(function (obj, path) {
        obj[path.split("/").pop()] = fs.statAsync(path).then(function (stat) {
            if (stat.isDirectory())
                return fs.readdirAsync(path).map(function (p) {
                    return path + "/" + p;
                }).then(getFiles);
            else if (stat.isFile())
                return fs.readFileAsync(path);
        }).error(function (e) {
            console.error("unable to read " + path + ", because: ", e.message);
            // return undefined; implied
        });
        return obj;
    }, {}));
}

答案 1 :(得分:1)

我不知道Bluebird,但这是ES6 Promise方法。

var fs = require('fs');
var directories = ['/dir1', '/dir2'];
var result = {};
Promise.all(directories.map(function(dir) {
  result[dir] = {};
  return new Promise(function(resolve, reject) {
    fs.readdir(dir, function(er, files) {
      if (er) {
        return reject(er);
      }
      resolve(files);
    });
  }).then(function(files) {
    return Promise.all(files.map(function(file) {
      return new Promise(function(resolve, reject) {
        fs.readFile(dir + '/' + file, function(er, data) {
          if (er) {
            return reject(er);
          }
          result[dir][file] = data.toString('base64');
          resolve();
        });
      });
    }));
  });
})).then(function() {
  console.log(result);
}).catch(function(er) {
  console.log(er);
});