I drafted a code example to better understand Promise chaining and found myself quite confused about what's going on here.
Let's say we have two variables which store Promises:
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise 1');
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise 2');
}, 1000);
});
Then we chain them like that:
promise1
.then(data => {
console.log(data);
return promise2;
})
.then(data => {
console.log(data);
});
The two console.log
's seem to arrive simultaneously, although I would expect a 1 sec pause between them. Behavior is the same if I create functions which return promises and chain them instead:
function firePromise1() {
return promise1;
}
function firePromise2() {
return promise2;
}
firePromise1()
.then(data => {
console.log(data);
return firePromise2();
})
.then(data => {
console.log(data);
});
And only if I create a promise "on the go" (either inside the function called in promise chain or in then()
block itself), I see promises resolved one after another, with 1 sec interval:
promise1
.then(data => {
console.log(data);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise 2');
}, 1000);
});
})
.then(data => {
console.log(data);
});
Can someone please explain why it works that way? Is it about how JS initializes variables and somehow connected to the fact that "Promise executes immediately" (https://hackernoon.com/functional-javascript-resolving-promises-sequentially-7aac18c4431e)? I looked deep into different resources and docs but still seem to miss something important or even obvious... Thanks!
For the first two promise chains involving the declaration of promise1
and promise2
as variables, that is :
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise 1');
}, 1000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise 2');
}, 1000);
});
When you declare and assign variables, the right hand side of the assignment operator evaluates instantly, that is, both setTimeout
functions start immediately. It has nothing to do with a promise 'being executed'. You can test this by having a console.log("Print me!")
inside both setTimeout
functions.
If you declared the promises inside the following functions and then created a then()
chain you would have seen a one second delay between the logging of promise1 and promise2.
function prom1(){
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise 1');
}, 1000);
});
}
function prom2(){
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise 2');
}, 1000);
});
}