【问题标题】:Callback queue order in small node.js example小 node.js 示例中的回调队列顺序
【发布时间】:2015-08-13 02:30:17
【问题描述】:
"use strict"

const
    fs = require('fs'),
    stream = fs.createReadStream("file.txt"),
    timeout = 0;

stream.on('data', function() {
    console.log("File Read");
});

setTimeout(function(){
    console.log("setTimeout : " + timeout);
}, timeout);

我正在学习 node.js / javascript,我想知道为什么这个程序会返回

setTimeout : 0
File Read

而不是相反。

如果我错了,请纠正我,但在 javascript 中,回调队列是先进先出,先堆叠 stream,然后先出?

我认为由于nodejs 的非阻塞性质,两个回调都“并行”运行,setTimeout 首先完成并返回(例如,1000 毫秒的超时会切换结果。)

【问题讨论】:

    标签: javascript node.js callback event-loop


    【解决方案1】:

    如果我错了,请纠正我,但在 javascript 中,回调队列是 fifo, 先把流先堆叠出来?

    不完全是。异步回调按照它们完成它们的操作的顺序进行FIFO处理,而不是按照它们的操作开始的顺序。因此,操作完成所需的时间对于确定何时安排回调非常重要。短操作可能会在长操作之前完成,即使它们是稍后开始的。

    打开一个文件并开始读取它需要时间,setTimeout() 不需要时间,所以它首先出现。当您有独立的异步操作时,您几乎永远无法“知道”它们将按什么顺序发生,因为这取决于各种函数的内部时序。

    readStream 操作在计时器启动之前开始,但计时器在 readStream 操作获取其第一个数据之前完成,这只是由于两个异步操作内部所需的工作量。

    我认为由于 nodejs 的非阻塞特性,两者 回调以“并行”方式运行,并且 setTimeout 首先完成 返回(例如 1000 毫秒的超时将切换结果。)

    是的,这是正确的。


    这样想。你有两个强大的扩音器和一个非常好的麦克风。您设置了两个目标,将扩音器指向并收听返回的回声。一个目标,即非常近,一个目标非常远。你先用扩音器对着很远的目标,然后立即用扩音器对着近处的目标。毫不奇怪,即使您在第一个目标之后发出爆炸声,您也会首先收到来自近处目标的回声,这仅仅是因为来自远处目标的回声需要更长的时间才能穿过其所有额外距离并返回给您。您的 readStream 也是如此。即使您先启动它,它也比 setTimeout(fn, 0) 花费的时间要长得多,因此 setTimeout() 先完成,因此首先调用它的回调。


    如果时间对您很重要,那么您应该使用诸如 Promise 之类的工具来专门对您的异步操作进行排序,或者等待所有必要的结果都准备好。一个好的设计不应该“假设”一个异步操作将在另一个之前完成,除非您的代码通过对操作进行排序来明确保证这一点。

    【讨论】:

      【解决方案2】:

      令人惊讶的是,我在 2 天前做了一个视频教程来解释这个概念,而你却问了这个问题。 Do watch this 9 min video to get a good understanding of this.这里是解释。在 Nodejs 和一般的 JS 中有一个称为 Eventloop 的概念。 Eventloop 的作用是监视正在运行的代码和堆栈上的代码。正如您所说,从代码块压入堆栈的是 FIFO。但是,如果有任何异步或回调方法或必须执行的操作,则 Eventloop 会跳入操作以处理这些。什么 eventloop 本质上做了 8s,它有一个自己的队列来维护这些回调方法。当堆栈空闲时,队列中的这段代码被放入堆栈并被执行。

      【讨论】:

        【解决方案3】:

        这纯粹是因为 node js 的 IO 非阻塞特性。您的文件读取操作是一个 IO 操作,因此它将被推送到事件队列,并且 setTimeOut 函数将立即执行。文件读取完成后,使用其回调将加入主控制流。因此 setTimeOut 将首先执行,然后读取文件。很简单。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-01-27
          • 1970-01-01
          • 1970-01-01
          • 2021-11-10
          • 2016-08-29
          • 2018-08-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多