Javascript 如何确定所有异步readFile()调用完成后
我在文件目录上循环,对于每个位置,我都使用异步Javascript 如何确定所有异步readFile()调用完成后,javascript,node.js,Javascript,Node.js,我在文件目录上循环,对于每个位置,我都使用异步fs.readFile()读取该目录中的文件。如何最好地确定所有异步readFile()调用是否已完成?一般策略是通过从fs.readFile回调中增加共享计数器来跟踪已读取的文件数。然后,当这个计数器等于文件总数时,您就知道完成了。例如: function readFiles(paths, callback) { var processed = 0, total = paths.length; // holds results
fs.readFile()
读取该目录中的文件。如何最好地确定所有异步readFile()
调用是否已完成?一般策略是通过从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);
}
}
}
}
如果您在节点0.11.13或更高版本上,还可以使用本机承诺,特别是
Promise.all
,它接受一系列承诺并等待所有承诺得到解决:
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'], function (results) {
var oneTxtContents = results[0];
var twoTxtContents = results[1];
});
readFiles(['one.txt', 'two.txt']).then(function (results) {
var oneTxtContents = results[0];
var twoTxtContents = results[1];
});
最后,有许多库使这项(相当常见的)任务变得更容易 对于基于回调的并行异步任务,可以使用库: 对于基于Promise的并行异步任务,您可以使用Promise库,如,它包含节点样式函数的“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];
});
promise图书馆在这里会有所帮助-您是否签出了
bluebird
?在这种情况下,这有什么帮助?这还不只是处理单个异步调用吗?不,你可以使用Bluebird循环异步调用并映射结果-好的,谢谢-这很有意义。我最终使用了tymeJV对Bluebird的建议,并使用了它的.map()
,它基本上就是你所描述的。
// 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];
});