只要 javascript 在代码执行方面是“单线程”的(不包括 web 工作者之类的) ,这种情况就会一直发生。在大多数情况下,单线程的特性是一个巨大的简化,但是需要非阻塞习惯用法才能成功。
在浏览器或节点中尝试这段代码,您会发现不能保证准确性,相反,setTimeout 会非常晚:
var start = Date.now();
// expecting something close to 500
setTimeout(function(){ console.log(Date.now() - start); }, 500);
// fiddle with the number of iterations depending on how quick your machine is
for(var i=0; i<5000000; ++i){}
SetTimeout 的语义与 Web 浏览器中的语义大致相同: timeout 参数是执行前要等待的毫秒数 最低限度,而不是保证。此外,传递0,非数字,或负数字,将导致它等待一个最小数量的 ms 在节点,这是1毫秒,但在浏览器中,它可以多达50毫秒。
原因是 JavaScript 不能抢占 JavaScript:
setTimeout(function () {
console.log('boo')
}, 100)
var end = Date.now() + 5000
while (Date.now() < end) ;
console.log('imma let you finish but blocking the event loop is the best bug of all TIME')