Reputation: 43
This question is similar to my previous "The execution order of the promise according to the return type", but it is a little different.
Why is the order of execution of caseA and caseB different?
The difference between the code is "return" or "return promise"
caseA: 914258367
<html>
<head>
<script>
var promise = Promise.resolve();
promise = promise.then(function(rtnVal) {
console.log('1');
var promise2 = Promise.resolve();
promise2 = promise2.then(function(rtnVal) {
console.log('2');
});
promise2 = promise2.then(function(rtnVal) {
console.log('3');
});
console.log('4');
return;
});
promise = promise.then(function(rtnVal) {
console.log('5');
var promise2 = Promise.resolve();
promise2 = promise2.then(function(rtnVal) {
console.log('6');
});
promise2 = promise2.then(function(rtnVal) {
console.log('7');
});
console.log('8');
return;
});
console.log('9');
</script>
</head>
</html>
caseB: 91423 -> 5,6,7,8 don't even run
<html>
<head>
<script>
var promise = Promise.resolve();
promise = promise.then(function(rtnVal) {
console.log('1');
var promise2 = Promise.resolve();
promise2 = promise2.then(function(rtnVal) {
console.log('2');
});
promise2 = promise2.then(function(rtnVal) {
console.log('3');
});
console.log('4');
return promise;
});
promise = promise.then(function(rtnVal) {
console.log('5');
var promise2 = Promise.resolve();
promise2 = promise2.then(function(rtnVal) {
console.log('6');
});
promise2 = promise2.then(function(rtnVal) {
console.log('7');
});
console.log('8');
return promise;
});
console.log('9');
</script>
</head>
</html>
Upvotes: 0
Views: 90
Reputation: 29282
In the 2nd example, promise
in return promise;
in the 1st then
method call fulfillment handler refers to the promise returned by the 2nd then
method call.
This creates a situation where the promise returned by the 2nd then
method (let's call it p2
) waits for the promise returned by the 1st then
method (let's call it p1
) to settle. In short, p1
is waiting for p2
to settle, and p2
is waiting for p1
to settle, creating a deadlock.
This prevents the 2nd then
method fulfillment handler from getting invoked because promise
, i.e. p1
never fulfills.
Following code is a simplified version of what your code is doing:
const p1 = Promise.resolve();
const p2 = p1.then(() => p3); // p2 will always be in pending state
const p3 = p2.then(() => console.log("done")); // fulfillment handler never called
The fulfillment of p2
in the above code example depends on the return value of the p1.then(...)
method. But the value being returned is p3
, and p3
is waiting for p2
to settle. This puts the code in a situation where p2
is waiting for p3
to settle, and p3
is waiting for p2
to settle, creating a deadlock.
In the 2nd example,
promise
inreturn promise;
in the 1stthen
method call fulfillment handler refers to the promise returned by the 2ndthen
method call.
Why?
To understand this, let us first assume that the promise returned by Promise.resolve()
is p1
, the promise returned by 1st then
method call is p2
, and the promise returned by the 2nd then
method call is p3
.
Keeping the above in mind, after the following line, promise
refers to p1
:
var promise = Promise.resolve();
On the next line, after the 1st then
method call:
promise = promise.then(function(rtnVal) {
// 1st then...
});
The value of the promise
variable is overwritten with p2
.
Then after the 2nd then
method call:
promise = promise.then(function(rtnVal) {
// 2nd then...
});
The value of the promise
variable is overwritten with the promise p3
.
Until this point, the fulfillment handlers haven't been called yet. After the synchronous execution of your code ends, the asynchronous execution will start, resulting in the invocation of the fulfillment handler of the 1st then
method call.
As this handler returns promise
variable which now refers to the promise p3
, you have a deadlock: the promise p2
(returned by 1st then
) waiting on p3
, and the promise p3
waiting on p2
to settle before the fulfillment handler of the promise p2
can be invoked.
Upvotes: 2