【问题标题】:Javascript internals - clearTimeout just before it firesJavascript 内部 - clearTimeout 就在它触发之前
【发布时间】:2014-06-10 09:47:00
【问题描述】:

假设我这样做:

var timer = setTimeout(function() {
    console.log("will this happen?");
}, 5000);

然后在不到 5 秒后,另一个回调(例如来自 NodeJS 中的网络事件)触发并清除它:

clearTimeout(timer);

是否有可能来自 setTimeout 调用的回调已经在队列中等待执行,如果是这样,clearTimeout 是否会及时停止它?

为了澄清,我说的是 setTimeout 时间实际上到期并且解释器开始执行它的过程,但另一个回调当前正在运行,因此消息被添加到队列中的情况。这似乎是很容易忽略的竞争条件类型之一。

【问题讨论】:

    标签: javascript node.js settimeout event-loop


    【解决方案1】:

    即使 Node 是单线程的,问题描述的竞争条件也是可能的。

    这可能是因为计时器是由本机代码(在 lib_uv 中)触发的。 最重要的是,Node 将具有相同超时值的计时器分组。因此,如果您在同一毫秒内安排两个具有相同超时时间的计时器,它们将立即添加到事件队列中。

    但请放心,节点会在内部为您解决这个问题。引用节点 0.12.0 的代码:

    timer.js > clearTimeout

    exports.clearTimeout = function(timer) {
      if (timer && (timer[kOnTimeout] || timer._onTimeout)) {
        timer[kOnTimeout] = timer._onTimeout = null;
        // ...
      }
    }
    

    在清除超时时,Node 会在内部删除对回调函数的引用。因此,即使发生竞态条件,也不会造成任何伤害,因为这些计时器将被跳过:

    listOnTimeout

    if (!first._onTimeout) continue;
    

    【讨论】:

      【解决方案2】:

      Node.js 在单线程中执行。

      因此不会有任何竞争条件,您可以在超时触发之前可靠地取消它。

      另见a related discussion (in browsers).

      我说的是setTimeout时间实际到期,解释器开始执行它的过程

      如果没有查看 Node.js 的内部结构,我认为这是不可能的。一切都是单线程的,所以当你的代码运行时,解释器不能“在”做任何事情。

      您的代码必须在触发超时之前返回控制权。如果你在你的代码中加入一个无限循环,整个系统就会挂起。这都是“合作多任务”。

      【讨论】:

      • 我认为Node.js executes in a single thread. So there cannot be any race conditions 不合适。对于一个很好的解释,请参阅此评论 blog.raananweber.com/2015/06/17/… 也许这会引发关于“竞争条件”定义的讨论
      【解决方案3】:

      此行为在 HTML 标准中为 defined,触发的任务以:

      如果活动计时器列表中的句柄条目已被清除,则中止这些步骤。

      因此,即使任务已经排队,它也会被中止。

      然而,这是否适用于 Node.js 是值得商榷的,正如 the documentation 所说:

      Node.js 中的计时器函数实现了与 Web 浏览器提供的计时器 API 类似的 API,但使用了不同的内部实现,它围绕 Node.js 事件循环构建。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多