Sachin Jani Sachin Jani - 1 month ago 8
Javascript Question

JavaScript Promises : Chaining promise confusion

I've been playing with the Promises and the chaining doesn't return the expected result.
Following is the very simple example in which getHeroChain() function works as expected but the getHeroUnChain() function doesn't . Both's execution order is perfect as expected but in getHeroUnChain() that last 'then' function doesn't return the expected value(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

Please help me out with this little thing which seems to be little confusing to me.

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

Answer

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;