是否有必要(是否有意义)在 setTimeout 为 0 毫秒后调用 clearTimeout?
是必要的如果目的是防止异步定时器回调运行。执行顺序可以完全根据何时回调被调用来讨论。
首先,0 毫秒的值作为延迟意味着“尽快运行回调”(来自未来的异步上下文),但是:
它确实没有改变how setTimeout works;和
0 is not the actual value used 无论如何。
传递的函数会立即附加到回调队列中,所以我假设 clearTimeout 没有(也不能)做任何事情。
这是不正确的。传递的函数不是“立即附加到回调队列”。相反,当超时到期定时器仍然处于活动状态,回调函数将被调用。可能还有其他异步回调 - 来自计时器或其他 - 可以提前运行。
此外,所有剩余的同步代码都保证在定时器回调发生之前运行:在此上下文中清除超时可防止定时器回调被调用,无论同步代码所用的时间如何.
即使它不做任何事情,在这些情况下总是调用 clearTimeout 是不是“最佳实践”?
调用 clearTimeout 要么
阻止回调执行,如果在回调之前清除(因为它删除了计时器),或者;
如果回调已经发生(因为计时器不再活动),则不执行任何操作
因此,代码/算法的正确运行需要清除计时器;或者这是一个无用的操作。创建一个定时器只是为了立即取消它可能没有意义,但这是关于代码结构的题外话..
我还注意在适当的位置调用 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);