简体   繁体   中英

JavaScript Promises: Chaining promise confusion

I've been playing with Promises and the chaining in the following example doesn't return the expected result. The getHeroChain() function works as expected, but the getHeroUnChain() function doesn't. In both cases, the execution order is as expected, but, in getHeroUnChain() , that last then function doesn't return the expected value (the HEROES array).

var HEROES = [{
    id: 11,
    name: 'Mr. Nice'
}, {
    id: 12,
    name: 'Narco'
}, ];

function getHeros() {
    return Promise.resolve(HEROES); // resolved promise
}

function getHerosSlowlyChained() {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            console.log(" 1) inside setTimeout");
            resolve(2);
        }, 2000);

    }).then(function(value) {

        console.log(" 2) setTimeout resolved");
        console.log(" 2) inside 1st 'then' with value : " + value);
        return getHeros(); //return promise
    });
}

function getHerosSlowlyUnchained() { //not directly chained
    var mainPromise = new Promise(function(resolve, reject) {
        setTimeout(function() {
            console.log(" 1) inside setTimeout");
            resolve(2);
        }, 2000);
    });

    mainPromise.then(function(value) {

        console.log(" 2) setTimeout resolved");
        console.log(" 2) inside 1st 'then' with value : " + value);
        return getHeros(); //return promise

    });

    return mainPromise;
}

//Chained
function getHeroChain() {

    var heroPromise = getHerosSlowlyChained();

    heroPromise.then(function(heroes) {
        console.log(" 3) inside final 'then' with heroes :");
        console.log(heroes);
    });

}
//Un-Chained
function getHeroUnChain() {

    var heroPromise = getHerosSlowlyUnchained();

    heroPromise.then(function(heroes) {
        console.log(" 3) inside final 'then' with heroes :");
        console.log(heroes);
    });

}

//getHeroChain();
getHeroUnChain();

Output of getHeroChain() :

1) inside setTimeout
2) setTimeout resolved
2) inside 1st 'then' with value : 2
3) inside final 'then' with heroes : [Object, Object]

Output of getHeroUnChain() :

1) inside setTimeout
2) setTimeout resolved
2) inside 1st 'then' with value : 2
3) inside final 'then' with heroes : 2

JSBIN link : https://jsbin.com/pivoyuyawu/edit?js

This is because you return mainPromise in getHerosSlowlyUnchained . Every call to then or similar methods returns a new promise in the chain.

In getHeroChain , your chain is: setTimeout -> setTimeout resolved -> final then .

In getHeroUnChain your chain is: setTimeout -> [ setTimeout resolved , final then ].

Note that in the second example, both setTimeout resolved and final then are after setTimeout . This means that both are given 2 .

To fix, either do

return mainPromise.then(function(value) {

    console.log(" 2) setTimeout resolved");
    console.log(" 2) inside 1st 'then' with value : " + value);
    return getHeros(); //return promise

});

or

mainPromise = mainPromise.then(function(value) {

    console.log(" 2) setTimeout resolved");
    console.log(" 2) inside 1st 'then' with value : " + value);
    return getHeros(); //return promise

});
return mainPromise;

.then() always generate a new promise, so in your UnChained function, you should return the new promise, instead of the old mainPromise

function getHerosSlowlyUnchained() { //not directly chained
    var mainPromise = new Promise(function(resolve, reject) {
        setTimeout(function() {
            console.log(" 1) inside setTimeout");
            resolve(2);
        }, 2000);
    });

    // this will generate a new promise, you should return the new one
    // instead of the old mainPromise
    mainPromise.then(function(value) {

        console.log(" 2) setTimeout resolved");
        console.log(" 2) inside 1st 'then' with value : " + value);
        return getHeros(); //return promise

    });

    return mainPromise;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM