我有以下代码:
for (var i = 0; i < files.length; i++) {
var data = fs.readFileSync(files[i]);
fs.appendFileSync("file_part", data);
}
我们说我有1000个文件。它是for循环异步吗?或者我的应用程序将等到它完成该过程?
如果它同步,我如何使它异步?所以每个迭代都是异步的吗?
修改:
此代码是使用express
的服务器代码的一部分。我们收到了很多https请求,并为客户提供服务。其中一个操作是将1MB的文件附加到一个大文件中。如果操作成功,服务器应返回200,否则返回500.
问题在于,如果执行上面的代码(for循环),快递模块将停止为其他客户端提供服务,并且它会忙碌&#34;有这个要求。我尝试使用async.eachSeries
(因为文件的顺序有意义,所以我必须使用Series方法),但它仍然卡在服务器上。
答案 0 :(得分:1)
JS中的所有控制结构都是同步执行的。由于您在循环体中没有使用异步函数(但是明确同步的对应函数),它将等待它们完成任务。
要使代码段无阻塞,您需要使用常规的异步fs
方法,并对其进行适当的链接。我建议使用promises,但是如果你已经使用async.js,那么它应该是这样的:
async.eachSeries(files, function(file, cb) {
fs.readFile(file, function(err, data) {
if (err) return cb(err);
fs.appendFile("file_part", data, cb);
});
}, function(err) {
// call back to express here with 500 if err and 200 otherwise
});
答案 1 :(得分:0)
问题和你要做的事情都有几个问题。您可能想要澄清问题或澄清您真正想做的事情。
对您的问题的简短回答:否.A循环本身不是异步的。
答案略长:目前尚不清楚您是否需要将循环本身设为异步,但您可能只希望内容为异步。因此,您可能希望使用readFileSync
进行回调,而不是调用readFile
。在此回调中,您可以附加到该文件。这将“触发”1000个读取文件,这些文件将在准备好时调用它们的回调。
但仍然存在问题。如果您异步读取1000个文件,并将它们保存到您读取的同一个文件中,则不会以任何顺序获取文件内容,甚至可能有文件内容交错。我无法想象为什么你真的想要这样做。
更新:您更新的问题仍然有点模糊 - 如果您需要等到一切都完成后发送代码200回复...那么您将不得不等到所有附加文件。实际上没有任何其他解决方案。
但是,如果您可以立即返回代码200以指示您正在处理该文件追加,然后在后台执行追加,则可以将该循环作为异步任务的一部分执行。您可以在process.nextTick()
电话或承诺中或以对您的流量有意义的任何其他方式执行此操作。
答案 2 :(得分:0)
如果您只想异步连接文件列表,则可以在回调fs.readFile
中执行此操作:
function concatFiles (source_array, destination) {
var source = source_array.shift();
fs.readFile(source,function(err,data){
fs.appendFile(destination,data,function(err){
if (source_array.length) {
concatFiles(source_array, destination);
}
});
});
}
// Usage:
concatFiles(files,"file_part");
请注意,为清楚起见,我没有处理上面代码中的错误。在生产代码中,您应该检查错误并适当地处理它们。
相当明显的是发生了什么。弹出源列表中的第一个文件。然后异步读取该文件。然后,当完成时异步写入目标文件。重复,直到源列表为空。