Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What determines the call order of deferred function using promises or setTimeout?

Deferring the execution of functions, for example in custom event handling, is a common pattern in JavaScript (see, for example here). It used to be that using setTimeout(myFunc,0) was the only way to do this, however with promises there is now an alternative: Promise.resolve().then(myFunc).

I had assumed that these would pretty much do the same thing, but while working on a library which included custom events I thought I'd find out if there was a difference, so I dropped the following block into node:

var logfn=function(v){return function(){console.log(v)}};

setTimeout(logfn(1),0);
Promise.resolve().then(logfn(2));
logfn(3)();

I was expecting to see on the console 3, 1, 2 but instead I saw 3, 2, 1. So in other words the Promise is NOT equivalent to using setTimeout and comes out of the blocks first. At least in Node.

I repeated the test in Chrome and Firefox with the same result, however in Edge it came out as 3, 1, 2. I would also expect non-native promise libraries to use setTimeout under the hood so would come out the same as Edge.

What determines the order of these calls being resolved? What model is used by these different environments to determine execution order? Does any of the above represent standard or non-standard behaviour?

PS I'm defniately not suggesting relying on any of this staying consistant, I'm just curious.


After the answer given below pointed me in the right direction, and as mentioned briefly in the comment below, I found the complete answer in an excellent article by Jake Archibald (with an example almost identical to my code above) which I though I'd add up here rather than leaving it buried in a comment.

like image 857
Euan Smith Avatar asked Apr 20 '16 08:04

Euan Smith


People also ask

Which will execute first setTimeout or promise?

The reason the promise is executing before your timeout is that the promise isn't actually waiting for anything so it resolved right away.

Which is faster setTimeout or promise?

An immediately resolved promise is processed faster than an immediate timeout.

Is setTimeout a promise function?

setTimeout() is not exactly a perfect tool for the job, but it's easy enough to wrap it into a promise: const awaitTimeout = delay => new Promise(resolve => setTimeout(resolve, delay)); awaitTimeout(300). then(() => console.

Does promise all guarantee order?

While you'll get the resolution in the same order, there's no guarantee about when the promises are acted on. In other words, Promise. all can't be used to run an array of promises in order, one after the other.


1 Answers

ll depends how resolve() was internally implemented - probably you observe difference between setTimeout(fn, 0) and Edge implementations for setImmediate(fn)

Please consider the article - http://www.mattgreer.org/articles/promises-in-wicked-detail/ and the way how resolve method was implemented.

function resolve(value) {
    // force callback to be called in the next
    // iteration of the event loop, giving
    // callback a chance to be set by then()
    setTimeout(function() {
        callback(value);
    }, 1);
}

Than some explenations can be found at priority between setTimeout and setImmediate

From Microsoft documentation - https://developer.microsoft.com/en-us/microsoft-edge/platform/documentation/dev-guide/performance/efficient-script-yielding/ and one more link - setImmediate method

like image 68
Krzysztof Safjanowski Avatar answered Oct 21 '22 08:10

Krzysztof Safjanowski