Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Promise.resolve().then() is delayed?

I don't understand why resoved Promise delay .then() argument call?

example:

var myPromise = Promise.resolve();
console.log(myPromise);
myPromise.then(()=>console.log('a'));
console.log('b');

console return:

> Promise { <state>: "fulfilled", <value>: undefined }
> "b"
> "a"

If myPromise is fulfilled, why .then() don't call imediatly resolve function?

like image 609
Yukulélé Avatar asked Jul 04 '15 22:07

Yukulélé


People also ask

Does promise wait for resolve?

You can use the async/await syntax or call the . then() method on a promise to wait for it to resolve. Inside of functions marked with the async keyword, you can use await to wait for the promises to resolve before continuing to the next line of the function.

Why promises are faster than 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 .

What happens when a promise is resolved?

A Promise that is resolved with the given value, or the promise passed as value, if the value was a promise object. It may be either fulfilled or rejected — for example, resolving a rejected promise will still result in a rejected promise.

Is promise resolve the same as await?

Promise creation starts the execution of asynchronous functionality. await only blocks the code execution within the async function. It only makes sure that the next line is executed when the promise resolves. So, if an asynchronous activity has already started, await will not have any effect on it.


2 Answers

Because, by specification, promises call their resolve handler AFTER the current thread of execution unwinds and finishes back to "platform code". That guarantees that they are always called asynchronously.

So, thus you see the console.log('b') first as that thread of execution finishes and then the resolve handler is called where you see the console.log('a').

From the Promises/A+ specification:

2.2.4 onFulfilled or onRejected must not be called until the execution context stack contains only platform code. [3.1].

And, here's note [3.1]:

Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures that onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack. This can be implemented with either a “macro-task” mechanism such as setTimeout or setImmediate, or with a “micro-task” mechanism such as MutationObserver or process.nextTick. Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or “trampoline” in which the handlers are called.

This is done to provide consistent execution order so no matter when the promise is resolved (synchronously or asynchronously), the then() handlers are always called in the same timing relative to other code. Since many promises are resolved asynchronously, the only way to make a given promise consistent no matter how it is resolved is to make them always call their .then() handlers asynchronously.

like image 177
jfriend00 Avatar answered Oct 03 '22 14:10

jfriend00


jfriend00's answer is correct. Allow me to elaborate on why. Let's say I got myPromise from somewhere. I don't know it's just a Promise.resolve, it might resolve asynchronously, and it might not.

myPromise.then(function(){
     console.log("a");
});
console.log("b");

If the asynchronousity guarantee didn't exist - that would sometimes log a b and sometimes b a. This is a race condition, and is a terrible thing to have. Promises are not susceptible to this problem by design - and execution order is always guaranteed in new promises implementations and native promises in particular.

The actual implementation of running new jobs is via Job Queues. then enqueues a job to the job queue in the handler, and job queues are run after code is ready - this is specified here.

like image 27
Benjamin Gruenbaum Avatar answered Oct 03 '22 16:10

Benjamin Gruenbaum