Understanding the execution order of subsequent handlers () of resolved promises

I am learning Promise to figure this out, I read a little about the JavaScript event loop. This article briefly describes the operation of an event loop, such as a call stack, an event table, and a message queue.

But I don’t know how the call stack deals with the line containing "return", and what happens after that. The following is an example that I wrote to hopefully understand how Promise works based on an event loop. Also see http://jsbin.com/puqogulani/edit?js,console if you want to postpone it.

var p1 = new Promise( function(resolve, reject){ resolve(0); }); p1.then(function(val){ console.log(val); p1.then(function(){ console.log("1.1.1"); p1.then(function(){ console.log("1.1.2"); p1.then(function(){ console.log("1.1.3"); }); }); }); p1.then(function(){ console.log("1.2"); }) return 30; //return new Promise(function(resolve, reject){ // resolve(30); //}); }) .then(function(val){ console.log(val/2); }); p1.then(function(){ console.log("2.1"); }); console.log("Start"); 

As you can see, there are two "returns", with each of them giving a different output order. In particular, when using return 30; , 1.1.2, 1.1.3 after 15 , but when using return new Promise(...) , 1.1.2, 1.1.3 before 15 . So what exactly happened when the code reached two different "returns"?

+7
javascript callstack event-loop
source share
1 answer

The difference is described at http://promisesaplus.com/ in accordance with the promise resolution process.

For the first return value:

2.3.3.4 If then not a function, keep the promise with x.

For the second:

2.3.2 If x is a promise, accept its state [3.4]:

2.3.2.2 If / when executing x, keep the promise with the same value.

We see that this is implemented by q.js. This is one possible implementation, but seems to explain the delay:

 function coerce(promise) { var deferred = defer(); Q.nextTick(function () { try { promise.then(deferred.resolve, deferred.reject, deferred.notify); } catch (exception) { deferred.reject(exception); } }); return deferred.promise; } 

When returning a promise from the then function, we have two separate promise objects: one that returns from the function passed to then , and one that returns from then . They must be connected together to resolve the first, allows the second. This is done using promise.then(deferred.resolve, ...)

The first delay comes from Q.nextTick . This performs the function in the next iteration of the event loop. There is some discussion in commenting on comments about why this is necessary.

Calling promise.then adds the extra delay of one iteration of the event loop. As required in the specification:

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

The execution will look something like this:

 p1.then with function containing 1.1.1 is called function containing 1.1.1 is queued p1.then with function containing 1.2 is called function containing 1.2 is queued Promise resolving to 30 is returned Q.nextTick function is queued ---------- 1.1.1 is printed p1.then with function containing 1.1.2 is called function containing 1.1.2 is queued 1.2 is printed Q.nextTick function is executed promise.then(deferred.resolve, ...) is queued ---------- 1.1.2 is printed p1.then with function containing 1.1.3 is called function containing 1.1.3 is queued promise.then(deferred.resolve, ...) is executed function containing val/2 is queued ---------- 1.1.3 is printed val/2 is printed 
+2
source share

All Articles