2

我试图绕开我的脑袋,了解 javascript async 在单线程浏览器环境中是如何工作的。

作为异步,我们可以同时处理计时器和 xhr 请求。现在假设我有类似下面的东西

function doStuff() {
    for(var i=0; i<100000000; i++) {
        // do something to make proc busy
        if(i%1000 === 0) {
            console.log('in for loop');
        }
    }
}


setTimeout(function() {
    console.log('timed out')
}, 2);
doStuff();
doStuff();
doStuff();

计时器设置为非常小的值(2ms),所以我想它应该如下工作:

1) 定时器回调排队

2)doStuff()被执行(作为一个整体?),它需要一些时间(超过 2 毫秒)

doStuff()3)计时器回调运行,因为在一个执行和另一个执行之间有一个时刻

4) nextdoStuff()被称为

4)最后一个doStuff()被称为

相反,我看到的是所有三doStuff()件事都在计时器回调触发之前完成。而且它比那些 2ms 的时间要长得多。是的,我知道setTimeout不能保证设置的这个时间值。

我的问题是javascript如何执行代码?在调用异步队列中的某些内容之前将立即执行的最小的原子块是什么?

4

3 回答 3

5

你在这里错了:

3)计时器回调运行,因为在一个 doStuff() 执行和另一个执行之间有一个时刻

为什么在以下问题的答案中:

在调用异步队列中的某些内容之前将立即执行的最小的原子块是什么?

JavaScript 使用一种叫做事件循环的东西。每个事件循环周期都可以称为“滴答”。在每个滴答声中,解释器检查是否有要执行的异步回调(例如,setTimeout超时已过期的回调)。

所有其他同步操作都发生在同一滴答声中。因此,在您的示例中,将在下一个滴答中检查计时器是否到期,但所有三个调用doStuff都在当前滴答中执行。这就是为什么传递给的时间值setTimeout不能保证的原因:没有办法知道到下一个刻度需要多长时间,所以我们通常说回调将“尽快”运行。在 的情况下setInterval,甚至可能会掉线;例如,当下一个滴答发生在定义间隔的两倍之后,回调只运行一次。

于 2013-01-16T22:07:24.667 回答
3

由于 Javascript 是单线程的,因此只能在解释器空闲时处理超时。当您将超时功能排队时,解释器仍在处理您的主脚本,并且在完成之前无法处理超时。

setTimeoutorsetInterval或任何其他异步事件只会在没有代码运行时处理。他们不会中断当前的代码。任何阻塞的正在运行的 javascript 代码都会延迟所有事件处理程序的执行。

于 2013-01-16T22:03:20.510 回答
0

WebWorker 是 Async Javascript 的更新解决方案。对于 sencha 开发人员来说,这里是教程,仍然不依赖于 setTimeout

于 2014-01-31T12:36:43.323 回答