我有一个示例代码和输出如下: 的码:
for(var i = 0; i <20; i++) {
var fs = require("fs");
fs.readFile('input2.txt', function (err, data) {
if (err) return console.error(err);
console.log("first started\n");
console.log(data.toString());
});
console.log("first Ended");
console.log("second started");
var data = fs.readFileSync('input1.txt');
console.log(data.toString());
console.log("second Ended");
}
输出:
首先结束 第二次开始 第二个结束 第一个结束 第二次开始 等等20次 首先开始了 1 刚开始 1等等,直到20次
由于input2.txt中只有一个字符,而input1.txt中没有任何行。我假设在一次迭代后从第一个文件打印输入后将调用回调函数,因为文件读取操作应该在那时完成。但事实并非如此。意味着它首先完成同步操作然后只有回调才能正常工作。怎么可能呢?如果回调必须等待这么长时间,异步调用的目的是什么?
答案 0 :(得分:0)
您的for
循环同步运行并完成20 fs.readFile()
个操作,这些操作都是异步的(意味着它们将在稍后完成)。
然后,在for
循环结束后,异步操作将开始完成并逐个服务(不一定按照它们的启动顺序)。
因为node.js中你自己的Javascript是单线程的,这意味着你当前的执行线程运行完成,所以for
循环运行直到完成。 for
循环的每次迭代都会启动fs.readFile()
操作,这是异步操作。然后,当您的for
循环继续时,该操作将在后台运行。当每个fs.readFile()
操作完成时,其回调将添加到JS事件队列中。当您的当前执行线程完成(并且只有那时)时,Javascript解释器会将第一个项目拉出事件队列并运行它(如果此时事件队列中有任何内容)。如果此时事件队列中没有任何内容(因为没有任何异步操作尚未完成),那么JS引擎将等待下一个事件发生,并且当第一个异步操作完成并将回调放入事件队列时, JS引擎将为该事件提供服务并调用该回调。
这样的异步回调永远不会在Javascript执行过程中被调用。 JS是单线程的,因此在JS的当前线程完成之前不会调用这些异步回调。
虽然这个答案是在浏览器中为Ajax调用编写的,但是node.js中的事件队列概念是相同的,所以这也可能有助于解释:How does JavaScript handle AJAX responses in the background?
答案 1 :(得分:0)
当一个名为async的函数时,它的回调在node.js中的下一个tick中调用
在你的代码片段中,循环中的所有语句都在当前的tick中调用并执行。但是那个读取文件异步的回调,会在下一个滴答队列中执行。