我循环遍历文件目录,对于每个位置,我正在使用异步fs.readFile()
读取此目录中的文件。如何才能最好地确定所有异步readFile()
调用是否已完成?
答案 0 :(得分:0)
一般策略是通过从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];
});
如果您使用的是节点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']).then(function (results) {
var oneTxtContents = results[0];
var twoTxtContents = results[1];
});
最后,有许多库使这个(相当常见的)任务更容易。
对于基于回调的并行异步任务,您可以使用async库:
async.map(['one.txt', 'two.txt'], fs.readFile, function (err, results) {
var oneTxtContents = results[0];
var twoTxtContents = results[1];
});
对于基于Promise的并行异步任务,您可以使用像Q这样的Promise库,其中包含用于fs.readFile
等节点式函数“promisification”的实用程序:
// 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];
});