34

The jQuery source features uses of setTimeout with both 0 and 1 as second argument. I'm under the impression that they both mean "execute the function as soon as you can".

Is this correct? Is there a difference between the two?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Randomblue
  • 112,777
  • 145
  • 353
  • 547
  • 25
    1 ms difference... – Leon Dec 01 '11 at 13:01
  • 2
    @Leon: I was under the impression that browsers cannot execute with that level of precision, bumping up the `setTimeout` time to a minimum of 13 milliseconds. – Randomblue Dec 01 '11 at 13:03
  • never heard about that magical 13, but here's a quote: "setTimeout in most browsers doesn't allow a delay less than about 10 milliseconds (it forces any smaller delays to be longer)" – Leon Dec 01 '11 at 13:10
  • @Leon, You would think that 1MS would be the difference, but that depends on if there are other items in the event loop. – Adam Fowler Apr 21 '17 at 21:47

6 Answers6

30

setTimeout has a minimum timeout of 4ms. So there is actually no difference between the two.

If the currently running task is a task that was created by the setTimeout() method, and timeout is less than 4, then increase timeout to 4.

Spec

EDIT: As pointed out by Ahmad in the comments, the spec has changed now, so the answer would currently be, "It depends."

Some Guy
  • 15,854
  • 10
  • 58
  • 67
  • 1
    the day all browsers follow the Specs to the ms will be a great day for us web developers :D – Leon Dec 01 '11 at 13:11
  • the minimum timer resolution highly depends on platform and browser aswell. – jAndy Dec 01 '11 at 13:19
  • You're correct. Just tested [this](http://pastehtml.com/view/bfupz16za.html) out, and turns out, the difference is quite a lot. Sometimes it says 3 for me, and sometimes it says 146 for me. (Not fixed. Varies a lot) – Some Guy Dec 01 '11 at 13:20
  • 3
    actually - as far as I recall - the timeout you define is meant to be the earliest possible moment. If your cpu is heavily used your function fire might much later. – Valentin Apr 15 '13 at 15:32
  • 8
    Actually your assumption is wrong, and in the spec they mentioned that **If nesting level is greater than 5, and timeout is less than 4**, then increase timeout to 4. so this valid only when the nesting level is more than 5. – amd Aug 12 '13 at 14:12
  • 1
    @Ahmad Yep, you're right, it's been updated now. At the time of this answer, nearly 2 years ago, the spec had the words quoted in my answer. – Some Guy Aug 12 '13 at 16:40
  • From MDN, [`setTimeout()`, Reasons for delays longer than specified](https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout#Reasons_for_delays_longer_than_specified): "Historically browsers implement `setTimeout()` 'clamping': successive `setTimeout()` calls with delay smaller than the 'minimum delay' limit are forced to use at least the minimum delay. To implement a 0 ms timeout in a modern browser, you can use [`window.postMessage()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) as [described here](http://dbaron.org/log/20100309-faster-timeouts)." – gfullam Nov 02 '15 at 21:16
  • 1
    MDN also explains the use of `setTimeout()` with a Zero delay on their article [Concurrency model and Event Loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#Adding_messages). – gfullam Nov 02 '15 at 21:20
21

I think the answer is "It depends" now.

We can run the code in different platform and browsers:

function setTimeouts() {
  setTimeout(function() { console.log(2); }, 2);
  setTimeout(function() { console.log(1); }, 1);
  setTimeout(function() { console.log(0); }, 0);
}

for (var i = 0; i < 10; i++) {
  setTimeouts();
}
  1. For Node.js, 0 is converted to 1, so they are exactly the same: https://github.com/nodejs/node/blob/master/lib/timers.js#L319, and result might be:

     1
     0
     1
     0
     1
     0
     1
     0
     1
     0
     1
     0
     1
     0
     1
     0
     1
     0
     1
     0
     2
     2
     2
     2
     2
     2
     2
     2
     2
     2
    
  2. For Chrome, the result is quite similar with Node.js

  3. For Firefox, most of 0 will be printed before 1:

     0
     0
     0
     0
     0
     0
     0
     0
     0
     0
     1
     1
     1
     1
     1
     1
     1
     1
     1
     1
     2
     2
     2
     2
     2
     2
     2
     2
     2
     2
    
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Freewind
  • 193,756
  • 157
  • 432
  • 708
  • Yes Chrome has a minimum timeout of 1ms currently, but they are working on removing that limitation eventually: https://crbug.com/402694 Node.js also has the same 1ms minimum, but not Firefox (though [they do have weirdnesses](https://bugzil.la/1270059) too where callbacks scheduled before the page load have less priority than others) – Kaiido Mar 15 '22 at 05:40
5

I'm not sure the given answers are correct. Running the following code in Chrome, 0 is clearly invoking the bound function more quickly (just switch the timer values between 0 and 1):

console.log("A");
console.log("B");
var start = new Date().getTime();
setTimeout(function() {
    console.log(new Date().getTime() - start);
}, 0);
console.log("C");
console.log("D");

0 seems to be doing something like Node.js's setImmediate, pushing an instruction onto the end of the current call stack, while 1 invokes whatever the implementation regards as a minimum value.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sandro Pasquali
  • 403
  • 4
  • 9
  • Minor correction: The function you're referring to in Node is called process.nextTick, while setImmediate is a new introduction into IE10 that does the same thing. – Paul Gordon Apr 29 '14 at 01:13
  • I found no consistent advantage to using `0` vs `1` in the above test. Sometimes the output was greater with `0` and sometimes it was greater with `1`. – gfullam Nov 02 '15 at 20:12
2

Programmatically and computationally there is a difference, but it is not a difference you will see when you execute it, as it is only 1 ms.

I would imagine that if the timeout is set to 1 ms, it pauses that script and allows other scripts to run meanwhile. And as you probably know, JavaScript is singlethreaded, so that might be your reason right there.


Thanks to molf who corrected my thoughts. It would seem that setting it to  ms is merely a trick to get it to run in the next tick of the event loop.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jan Dragsbaek
  • 8,078
  • 2
  • 26
  • 46
  • 3
    Why wouldn't that happen with `0ms` too? Do you have any sources? – molf Dec 01 '11 at 13:09
  • It would only make sense that if set to 0ms, it would run instantly. I have no sources, hence why i wrote "I would imagine" – Jan Dragsbaek Dec 01 '11 at 13:11
  • 4
    Setting it to `0` is a common trick to have the code run in the next tick of the event loop, it should not run instantly at all. – molf Dec 01 '11 at 13:12
  • @JanDragsbaek setTimeout is asynchronous. Further more it has a minimum timeout of 4, 10 or 13ms depending on your browser. – Raynos Dec 01 '11 at 13:15
1

For reasons why setTimeout(fn, 0) or setTimeout(fn, 1) is needed, check out Why is setTimeout(fn, 0) sometimes useful?.

In essence, it means that this method is not very urgent to execute compared to other browser tasks like page rendering. Moreover, the JavaScript code will run after the waiting tasks are over.

Practical wise, there is no difference between using 0 or 1. This is just programmer's choice. Ideally the number chosen by coders is below 4 which may be due to the reason pointed out by Amaan.

BTW, for basic information on JavaScript timers, refer to http://ejohn.org/blog/how-javascript-timers-work/

zhulien
  • 5,145
  • 3
  • 22
  • 36
sv_in
  • 13,929
  • 9
  • 34
  • 55
-1

It's simply an example of bad code practice in the jQuery source.

That's all. There's no reason to favor 0 over 1 or vice versa.

Raise a jQuery bug, have it fixed / normalized to use one or the other.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Raynos
  • 166,823
  • 56
  • 351
  • 396
  • please define "bad code". Do you think there is a solution without using `setTimeout` (crossbrowser) or just because they used 1/0 ? The Former I'd be curious on your suggestion, the latter is probably a code smell at best. – jAndy Dec 01 '11 at 13:22
  • 4
    @jAndy I meant the fact they use both 0 and 1 in the source code. That kind of thing shouldn't go past code review. jQuery should have a decent style guide and apply it rigoriously – Raynos Dec 01 '11 at 13:28