使用q的诺言与地图获取文件内容

我正在尝试使用q promise库来获取目录中的.json文件的名称并返回这些文件的内容。 我能够得到文件名,但是我在使用arr.map和promise来读取文件的内容时遇到了麻烦。 我想getContents()返回一个映射数组与指定的文件名的内容。

 function readDir() { var deferred = q.defer(); fs.readdir('users', function(err, data) { if (err) console.log(err); deferred.resolve(data); }) return deferred.promise; } function getContents(filenames) { return filenames.map(function(filename) { fs.readFile('users/' + filename, 'utf8', function(err, result) { return result; }); }); } readDir() .then(getContents) .then(function(fileContents) { // currently returns undefined console.log(fileContents); }); 

我如何正确包装getConents()在一个承诺,使我的数组内容不等于undefined?

首先,你需要得到一个promise数组 – return result在asynchronouscallback中是没用的。 为每个readFile调用作出承诺:

 filenames.map(function(filename) { return Q.nfcall(fs.readFile, 'users/' + filename, 'utf8'); // ^^^^^^ here's where the return is needed }) 

Q.nfcall函数基本上和你在readDir函数中写的readDir

现在你已经有了一系列的承诺,你可以使用Q.all轻松地把它变成对数组的承诺(等待所有的承诺):

 function getContents(filenames) { return Q.all(filenames.map(function(filename) { return Q.nfcall(fs.readFile, 'users/' + filename, 'utf8'); })); } 

首先,你可以使用promise来定义fs.readFile的正确的asynchronous版本:

 function readFileAsync(/* ...args */) { return Q.nfapply(fs.readFile, arguments); } 

之后,你有两个select。 这将并行读取文件:

 function getContents(filenames) { return Q.all( filenames.map(function(filename) { return readFileAsync('users/' + filename, 'utf8'); }) ); } 

这将逐一阅读:

 function qMap(array, selector) { var i = 0; var result = []; function store(x) { result.push(x); return next(); } function next() { if (i < array.length) { var index = i++; var item = array[index]; return Q.fcall(selector, item, index).then(store); } else { return result; } } return Q.fcall(next); } function getContents(filenames) { return qMap(filenames, function(filename) { return readFileAsync('users/' + filename, 'utf-8'); }); }