JavaScript 承诺:链接承诺混乱

JavaScript Promises: Chaining promise confusion

我一直在玩 Promises,下面示例中的链接没有 return 预期的结果。 getHeroChain() 函数按预期工作,但 getHeroUnChain() 函数没有。在这两种情况下,执行顺序都符合预期,但是在 getHeroUnChain() 中,最后一个 then 函数没有 return 预期值(HEROES 数组)。

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();

getHeroChain() 的输出:

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

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

这是因为你 return mainPromisegetHerosSlowlyUnchained。每次调用 then 或类似方法 return 都是链中的 new 承诺。

getHeroChain中,你的链是:setTimeout -> setTimeout resolved-> final then.

getHeroUnChain 你的链是:setTimeout -> [setTimeout resolved, final then].

请注意,在第二个示例中,setTimeout resolvedfinal then 都在 setTimeout 之后。这意味着两者都给出了 2.

要修复,要么做

return mainPromise.then(function(value) {

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

});

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() 总是生成一个新的承诺,所以在你的 UnChained 函数中,你应该 return 新的承诺,而不是旧的 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;
}