javascriptfunctionasynchronouspromiseexecution

The execution order of the promise according to the return type 2


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>

Solution

  • 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.

    Edit

    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.

    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.