The mystery of promise function then

Time:2020-6-12

Promise’s then method can accept the execution result of the previous function and guarantee the sequential execution of the other promise. How can this be done?

Schematic diagram (above)

The mystery of promise function then

Problem demand

How to ensure the sequential execution of multiple promises?
example:

var f1 = function (){
    return new  Promise(function (resolve, reject){
        setTimeout(function (){
            console.log("f1 ok!")
            resolve("f1 ok!");
        }, 1000)
    });
}
var f2 = function (){
    return new  Promise(function (resolve, reject){
        setTimeout(function (){
            console.log("f2 ok!")
            resolve("f2 ok!");
        }, 3000)
    });
}
var f3 = function (){
    return new  Promise(function (resolve, reject){
        setTimeout(function (){
            console.log("f3 ok!")
            resolve("f3 ok!");
        }, 2000)
    });
}

Of course, if it’s going to be parallel, it’s easy for us to think about it Promise.all method:

Promise.all([f1(), f2(), f3()]).then(function (data){
    console.log(data)
})
// f1 ok! 
// f3 ok! 
// f2 ok! 
// ["f1 ok!", "f2 ok!", "f3 ok!"]

If you want to execute in sequence:

f1().then(f2).then(f3)
// f1 ok!
// f2 ok!
// f3 ok!

//Or so

function f(all) {
    var promise = Promise.resolve();
    all.forEach((p, index) => {
        promise = promise.then(p)
    })
}
f([f1, f2, f3])

So the question is, how does then execute in order? Parameters can be either a normal function or a function that returns promise?

The mystery of then

Many libraries that implement promise are complex. If you implement it yourself, you can use the following simple code for reference:

Promise.prototype.then = function(onFulfilled, onRejected) {
    var promise = this;
    return new Promise(function(resolve, reject) {
        function handle(value) {
            var ret = typeof onFulfilled === 'function' && onFulfilled(value) || value;
            if (ret && typeof ret['then'] == 'function') {
                ret.then(function(value) {
                    resolve(value);
                }, function(reason) {
                    reject(reason);
                });
            } else {
                resolve(ret);
            }
        }
        function errback(reason) {
            reason = typeof onRejected === 'function' && onRejected(reason) || reason;
            reject(reason);
        }
        if (promise._status === 'PENDING') {
            promise._resolves.push(handle);
            promise._rejects.push(errback);
        } else if (promise._status === FULFILLED) { 
            callback(promise._value);
        } else if (promise._status === REJECTED) {
            errback(promise._reason);
        }
    });
}

Focus on the implementation of then. Look at the above code,What is returned by each then? A new promise, a new promise, a new promise
The second point is,Internally, a callback function is processed, and the result is a promise judgment, if so, wait for the end of the promise run before calling resolve to change the state,The key is when to call resolve, when to call resolve,These two steps are the key to the then function.
Is it a little dizzy? Please see the first picture.