【问题标题】:Is clearTimeout necessary after setTimeout with 0ms?setTimeout 0ms 后是否需要 clearTimeout?
【发布时间】:2015-09-15 08:11:42
【问题描述】:

正如我已经了解到的(此处:https://www.youtube.com/watch?v=8aGhZQkoFbQ),在某些情况下调用具有 0 毫秒延迟的 setTimeout 可能很有用(因为事件循环)。

现在,通常每当我使用setTimeout 时,我也会注意在适当的位置调用clearTimeout,以确保没有任何东西留在某处并在我不希望它被执行的地方被执行。

所以我的问题是:是否有必要(是否有意义)在 setTimeout 之后以 0ms 调用 clearTimeout?传递的函数会立即附加到回调队列中,所以我假设clearTimeout 没有(也不能)做任何事情。或者clearTimeout是否可以从回调队列中移除传递的函数(所以在超时之后但在函数执行之前)?

第二个问题:即使它没有做任何事情,在这些情况下总是调用clearTimeout 是不是“最佳实践”?

【问题讨论】:

    标签: javascript settimeout


    【解决方案1】:

    是否有必要(是否有意义)在 setTimeout 为 0 毫秒后调用 clearTimeout?

    必要的如果目的是防止异步定时器回调运行。执行顺序可以完全根据何时回调被调用来讨论。

    首先,0 毫秒的值作为延迟意味着“尽快运行回调”(来自未来的异步上下文),但是

    1. 它确实没有改变how setTimeout works;和

    2. 0 is not the actual value used 无论如何。

    传递的函数会立即附加到回调队列中,所以我假设 clearTimeout 没有(也不能)做任何事情。

    这是不正确的。传递的函数不是“立即附加到回调队列”。相反,超时到期定时器仍然处于活动状态,回调函数将被调用。可能还有其他异步回调 - 来自计时器或其他 - 可以提前运行。

    此外,所有剩余的同步代码都保证在定时器回调发生之前运行:在此上下文中清除超时可防止定时器回调被调用,无论同步代码所用的时间如何.

    即使它不做任何事情,在这些情况下总是调用 clearTimeout 是不是“最佳实践”?

    调用 clearTimeout 要么

    1. 阻止回调执行,如果在回调之前清除(因为它删除了计时器),或者;

    2. 如果回调已经发生(因为计时器不再活动),则不执行任何操作

    因此,代码/算法的正确运行需要清除计时器;或者这是一个无用的操作。创建一个定时器只是为了立即取消它可能没有意义,但这是关于代码结构的题外话..

    我还注意在适当的位置调用 clearTimeout 以确保没有任何东西留在某处并在我不希望它被执行的地方被执行。

    如上所述,无需手动清除不再活动的计时器;并且在调用定时器回调之前取消定时器将删除定时器,从而阻止定时器回调执行。

    何时/何地/是否应该取消计时器取决于整个设计。


    取消执行代码中的超时会阻止回调运行:“A”或“B”回调都不会运行。

    a = setTimeout(function () { console.log("A"); }, 0);
    clearTimeout(a);
    
    b = setTimeout(function () { console.log("B"); }, 0);
    s = Date.now()
    while (Date.now() - s < 100) { /* waste 100ms of CPU */ }
    clearTimeout(b);
    

    取消首先运行的异步事件中的超时会阻止回调运行:“B”回调永远不会运行:。

    a = setTimeout(function () { console.log("A"); clearTimeout(b); }, 0);
    b = setTimeout(function () { console.log("B"); }, 0);
    

    虽然使用了辅助计时器(因为可以很好地保证排序),但也有可能在“0ms”超时之前发生其他异步事件(按钮点击、Web Worker、AJAX 等)。

    在回调之后(从任何上下文)调用的 clearTimeout 是无用的:

    a = setTimeout(function () { console.log("A"); clearTimeout(a); }, 0);
    
    a = setTimeout(function () { console.log("A"); }, 0);
    b = setTimeout(function () { console.log("B"); clearTimeout(a); }, 0);
    

    【讨论】:

    • 完美!这就是我一直在寻找的答案。感谢您为描述所有不同案例所做的所有努力。非常感谢!
    【解决方案2】:

    clearTimeout 将删除该功能。在您的 Chrome 控制台中尝试此操作:

    var timer = setTimeout(function() { console.log('hello'); }, 0);
    clearTimeout(timer);
    

    【讨论】:

    • 这是一个正确的答案。 clearTimeout 确实会阻止回调运行。即使“排队”(一旦调用 setTimeout,它实际上就会排队),只要在 JavaScript 实际运行回调之前发生清除。此外,setTimeout 为 0 应用了一个最小非零值。
    • 它会显示未定义,而不是你好。
    • @simhumileco undefined 是 clearTimeout 的返回值,这说明了我的观点,即回调将被阻止运行,因为控制台没有记录任何内容。
    • OK @Lee 没关系。
    【解决方案3】:

    是否有必要(是否有意义)在 setTimeout 为 0 毫秒后调用 clearTimeout?

    没有。这是没有意义的。

    传递的函数会立即附加到回调队列中,所以我假设 clearTimeout 没有(也不能)做任何事情。

    如果你在与设置超时相同的函数中调用它,它可能会做一些事情,但那将是愚蠢的,如果你这样做,你不应该首先调用 setTimeout。

    即使它没有做任何事情,在这些情况下始终调用 clearTimeout 是否是“最佳实践”?

    没有。这是没有意义的。

    我还注意在适当的位置调用 clearTimeout 以确保没有任何东西留在某处并在我不希望它被执行的地方被执行。

    这里的关键词是“合适的位置”。通常没有合适的位置调用 clearTimeout。

    【讨论】:

    • 您也可以添加:Even if it does not do anything, is it anyway 'best practice' to call clearTimeout always in those cases? -- 如果您知道何时清除超时,则不会使用setTimeouts。您只需从那里调用您的函数。
    • 您好,感谢您的回答!您的第二条评论很有意义(顺便说一句。我不在同一个函数中调用setTimeoutclearTimeout)。但这真的仅限于功能范围吗?如果调用堆栈由于某些其他原因(其他异步调用)有一段时间没有变空怎么办?
    • 您是否有遇到特定竞争条件的代码?或者你认为可能会遭受一个?试图处理模糊的概括只会使事情复杂化。
    • 我问是因为我正在使用模块化方法和 require.js 开发单页应用程序,而我只开发单个模块。所以有很多事情我没有任何影响......所以从理论上讲,调用堆栈可能会在其他地方被填满。但我同意在这种情况下会有一个不同的(而且更严重的问题)。无论如何,谢谢。
    【解决方案4】:

    不,如果您打算执行超时,则不需要使用clearTimeout

    clearTimeout 方法仅用于停止执行超时。您可以停止超时,即使它的时间为 0 毫秒,因为在您退出函数并将控制权返回给浏览器之前,它不会被执行。

    【讨论】:

      【解决方案5】:

      const timeout = setTimeout(() => {
          console.log('sdfsdf');
          clearTimeout(timeout);
      }, 0);

      【讨论】:

      • 首先,不要将JS代码放在html部分。那么,你能解释一下为什么这段代码会解决这个问题吗?它似乎是 this answer 的副本,只是解释较少
      猜你喜欢
      • 2011-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-10
      相关资源
      最近更新 更多