看一下这个例子:
function A() { console.log('A'); }
function B() { console.log('B'); }
// and then i setTimeout(fn, 0) both of them
setTimeout(A, 0);
setTimeout(B, 0);
是否保证B
会在A
之后立即运行?
浏览器是否可能在A
和B
之间的队列中添加另一个任务?
注意:A
或B
函数都没有向事件循环添加任何新任务。
var callbacks = [];
// then add a bunch of callbacks ... (none adds events to event queue)
//case 1:
callbacks.forEach(cb => setTimeout(cb,0))
//case 2:
setTimeout(function() {
callbacks.forEach(cb => cb());
},0);
case 1
与case 2
的回调执行顺序有何不同?
答案 0 :(得分:3)
是否保证B会立即在A之后运行?
不立即,不,但保证B
将在A
之后运行。完整详细信息in the spec,但简而言之,timer initialization steps中明确说明了这一点:
等到此算法的任何具有相同方法上下文的调用(在此之前开始,并且其超时等于或小于此值)已完成。
(可选)等待用户代理定义的另一段时间。
将任务任务排队。
...其中任务是调用您提供的回调setTimeout
的任务。
任务队列必须按顺序运行,因此A
将在兼容浏览器上B
之前运行。
请注意,这是有保证的,因为它们是由相同的方法上下文排队的(有关详细信息,请参阅规范)。
浏览器是否可能在A和B之间的队列中添加另一个任务?
是。浏览器可以是多线程的,并在排队A
和B
的任务之间为某个其他事物(来自Web工作者的消息等)排队任务。在这种情况下,您会看到A
运行,然后是其他任务的处理程序(处理来自Web工作者的消息或其他任何内容),然后B
。
答案 1 :(得分:2)
他们将始终以正确的顺序触发,A
然后B
。但是,他们可能不会连续发射。
实际上,the specification says超时回调甚至没有放在执行队列上,直到计时器结束,这可能会受到额外的延迟 - 你指定的超时只是最小值等待的时间。
答案 2 :(得分:1)
JavaScript使用事件队列作为计时器。
另见本文: Excellent and still actual article about timers in JavaScript by John Resig.
答案 3 :(得分:-1)
是的,如果你试试这个:
function A() { console.log('A'); }
function B() { console.log('B'); }
function C() { while(1) { console.log('C'); } }
// and then i setTimeout(fn, 0) both of them
setTimeout(A, 0);
setTimeout(C, 0);
setTimeout(B, 0);
您将看到函数C具有无限循环,因此它永远不会执行函数B. 这是因为传递给任务/事件列表的函数在这些函数结束时运行。这与事件列表有关.setTimeout具有特定的工作方式。 但是,如果你问。
另一方面,如果您要求首先执行该案例,然后再执行B,则答案不能保证,因为它们不是唯一可以运行的事件。