如何确定所有asynchronousreadFile()调用已完成

我正在遍历文件目录,并为每个位置阅读这个目录中的文件与asynchronousfs.readFile() 。 如何才能最好地确定是否所有的asynchronousreadFile()调用已完成?

一般策略是通过从fs.readFilecallback中增加共享计数器来fs.readFile已经读取的文件数。 然后,当这个计数器等于文件总数时,就知道你已经完成了。 例如:

 function readFiles(paths, callback) { var processed = 0, total = paths.length; // holds results (file contents) in the same order as paths var results = new Array(total); // asynchronously read all files for (var i = 0, len = files.length; i < len; ++i) { fs.readFile(paths[i], doneFactory(i)); } // factory for generating callbacks to fs.readFile // and closing over the index i function doneFactory(i) { // this is a callback to fs.readFile return function done(err, result) { // save the result under the correct index results[i] = result; // if we are all done, callback with all results if (++processed === total) { callback(results); } } } } 

可以像这样使用:

 readFiles(['one.txt', 'two.txt'], function (results) { var oneTxtContents = results[0]; var twoTxtContents = results[1]; }); 

如果你在Node 0.11.13或更高版本上,你也可以使用本地promise,特别是Promise.all ,它接受一组promise,并等待所有的promise被parsing:

 function readFiles(paths) { // for each path, generate a promise which is resolved // with the contents of the file when the file is read var promises = paths.map(function (path) { return new Promise(function (resolve, reject) { fs.readFile(path, function (err, result) { if (err) { reject(err); } else { resolve(result); } }); }); }); return Promise.all(promises); } 

可以像这样使用:

 readFiles(['one.txt', 'two.txt']).then(function (results) { var oneTxtContents = results[0]; var twoTxtContents = results[1]; }); 

最后,还有一些库使得这个(相当普通的)任务更容易。

对于基于callback的并行asynchronous任务,可以使用asynchronous库:

 async.map(['one.txt', 'two.txt'], fs.readFile, function (err, results) { var oneTxtContents = results[0]; var twoTxtContents = results[1]; }); 

对于基于Promise的并行asynchronous任务,可以使用Q这样的Promise库,其中包含用于像fs.readFile这样的节点式函数的“promisification” fs.readFile

 // this is not the only way to achieve this with Q! Q.all(['one.txt', 'two.txt'].map(function (path) { // call "promisified" version of fs.readFile, return promise return Q.nfcall(fs.readFile, path); })).then(function (results) { // all promises have been resolved var oneTxtContents = results[0]; var twoTxtContents = results[1]; });