Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are equal timeouts executed in order in Javascript?

Suppose I do

setTimeout(foo, 0);

...

setTimeout(bar, 0);

Can I be sure foo will begin executing before bar? What if instead of 0 I use a timeout of 1, 10, or 100 for bar?

Simple experiments show that in the case of equal timeout values the timeout targets are executed in the same order as the setTimeouts themselves, but is it safe to rely on this behavior?

like image 334
jkl Avatar asked Nov 21 '09 18:11

jkl


People also ask

How does timeout work in JavaScript?

Introduction to JavaScript setTimeout()The setTimeout() sets a timer and executes a callback function after the timer expires. In this syntax: cb is a callback function to be executed after the timer expires. delay is the time in milliseconds that the timer should wait before executing the callback function.

Does JavaScript run code in order?

JavaScript is synchronous. This means that it will execute your code block by order after hoisting. Before the code executes, var and function declarations are “hoisted” to the top of their scope.

Which will execute first promise or setTimeout?

The reason the promise is executing before your timeout is that the promise isn't actually waiting for anything so it resolved right away. @frankies That has more to do with the way Promises are queued and resolved. The focus of my answer is the difference between setTimeout and Promise .

Why is setTimeout executed at last?

setTimeout schedules the function for execution. That scheduler doesn't do its thing until after the current thread yields control back to the browser, e.g. after the last logging statement has executed.


2 Answers

It is not safe to rely on this behavior. I wrote a test script which schedules a number of functions (and they in turn also schedule a number of functions) all using setTimeout(..., 0), and the order in which the functions were called was not always the same as the order in which setTimeout was called (at least in Chrome 11, which I used to run the script).

You can see/run the script here: http://jsfiddle.net/se9Jn/ (the script uses YUI for cross-browser compatibility, but Y.later uses setTimeout internally).

Note that if you just run the script and stare at the console, you will probably not see an offending ordering. But if start the script, switch to another tab, load some pages, and come back to the test page, you should see errors about callbacks out of order in the console.

If you need a guaranteed ordering, I would recommend scheduling the next function at the end of the previous function:

setTimeout(foo, 0);

...

function foo() {

    ...

    setTimeout(bar, 0);
}
like image 182
Stjepan Rajko Avatar answered Oct 28 '22 05:10

Stjepan Rajko


I read through the Firefox source code, and at least for that browser, there is a sequentiality guarantee for timeouts which are specified in nondecreasing order. Otherwise all bets are off.

Specifically, if in a given execution context you set a timeout for n, and then one for m, where n <= m, the targets will be executed in the order the timeouts were set.

But don't take my word for it. I believe the window implementation is in nsGlobalWindow.cpp, and the method which actually decides where timeouts go in the execution queue is called InsertTimeoutIntoList. It looks like the method traverses the queue backwards looking for the first timeout which is less than or equal to the given timeout, and inserts the given timeout after it.

Of course when the timeout is set the current clock time is added to the timeout value. This is why the timeout values must be in nondecreasing order for the targets to be executed in sequence.

like image 15
jkl Avatar answered Oct 28 '22 05:10

jkl