nodejs中的回调函数如何工作?

时间:2016-07-10 23:35:15

标签: node.js callback

我有一个示例代码和输出如下: 的

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中没有任何行。我假设在一次迭代后从第一个文件打印输入后将调用回调函数,因为文件读取操作应该在那时完成。但事实并非如此。意味着它首先完成同步操作然后只有回调才能正常工作。怎么可能呢?如果回调必须等待这么长时间,异步调用的目的是什么?

2 个答案:

答案 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中调用并执行。但是那个读取文件异步的回调,会在下一个滴答队列中执行。

请查看Process.nextTick