【问题标题】:Node.js setImmediate executed before I/O callbacks (Event Loop)Node.js setImmediate 在 I/O 回调之前执行(事件循环)
【发布时间】:2017-11-15 08:50:29
【问题描述】:

看看下面的代码:

var fs = require('fs');
var pos = 0;

fs.stat(__filename, function() {
 console.log(++pos + " FIRST STAT");
});

fs.stat(__filename, function() {
 console.log(++pos + " LAST STAT");
});

setImmediate(function() {
 console.log(++pos + " IMMEDIATE")
})

当我执行这段代码时,会显示以下结果:

正如 Node.js documentation 解释的那样,setImmediate 在 I/O 回调之后执行,但在此示例中 setImmediate 在 I/O 回调之前执行,我是否遗漏了什么?

【问题讨论】:

    标签: javascript node.js event-loop


    【解决方案1】:

    您期望的结果需要 fs.stat 方法立即返回 - 基本上是在当前事件循环结束之前。但是你的磁盘需要,比如说,2ms 来完成 I/O 操作。足够的时间来运行相当多的事件循环。发生的事情(现在很可能)是:

    Loop 0 starts
    fs.stat called
    fs.stat called
    immediate callback queued
    Loop 0 ends
    Loop 1 starts
    immediate callback gets called
    Loop 1 ends
    Loop 2 starts
    fs.stat completes, I/O callback queued
    fs.stat completes, I/O callback queued
    Loop 2 ends
    Loop 3 starts
    fs.stat I/O callback gets called
    fs.stat I/O callback gets called
    

    实际上,甚至没有人保证 fs.stat 1 在 fs.stat2 之前完成。所以你发布的结果也可能是

    1 IMMEDIATE
    2 LAST STAT
    3 FIRST STAT
    

    你可以做什么:

    1. 您可以使用 fs.stat 的同步版本。但是,尽管使用起来很舒服,但它会降低脚本的吞吐量,因为您将在 fs.stat 运行期间阻止脚本的执行。因此,如果您必须经常运行这部分代码,请使用以下方法之一!
    2. 您可能需要查看“await”以异步但按顺序运行代码
    3. 如果完成顺序对您来说并不重要,您也可以简单地使用 Promises 包装两个 fs.stat 调用。然后只做一个 Promise.all。或者您可以使用 async(一个库),它提供了许多处理异步性的功能
    4. ...

    【讨论】:

      【解决方案2】:

      setImmediate 不会等待所有 IO 操作完成。它只是优先考虑 IO 回调。在您在这里调用setImmediate 时,fs.stat 调用还没有完成,因此它们的回调还没有安排到事件循环中。

      【讨论】:

        猜你喜欢
        • 2023-02-03
        • 1970-01-01
        • 2011-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-26
        • 1970-01-01
        相关资源
        最近更新 更多