Reputation: 1429
When we chain a Promise's using chain, and the Promise is returned by then, so how code that isn't part of the then chain runs before the all chain was finished? How does the code jump over then calls? Shouldn't all then calls performed before running the "console.log" line of code?
Here is the code:
Promise.resolve('333')
.then((res)=>{console.log(res);return new Promise((resolve,reject)=> {setTimeout(function(){console.log('Timeout');resolve(1);},10000);console.log('Something');})})
.then((res)=>{console.log(res);return new Promise((resolve,reject)=> {console.log('Something');resolve(2);})})
.then((res)=>{console.log(res);return new Promise((resolve,reject)=> {console.log('Something');resolve(3);})})
.then((res)=>{console.log(res);return new Promise((resolve,reject)=> {console.log('Something');resolve(4);})})
console.log("When?")
In the output "When?" is being printed first.. Now i can't understand how is it possible since the callback in the first then will run only in about 10 seconds and only after that, the callback will return a Promise that will run the second then? Maybe i don't understand how the callback of then "goes with" the then function. I thought that then implementation looks a little bit like:
then(callback){
let value= callback();
if(value is promise){
return value;
}
return Promise.resolve(value)
}
Upvotes: 2
Views: 2323
Reputation: 1419
It’s because code inside a promise is asynchronous and asynchronous code is always executed after all the synchronous code has been executed.
In your example you have 2 sync instructions, the first row where you are setting up the promise chain and the console.log
. So first JavaScript is setting up the promises and then logging When
. Only after this it is going to resolve the promises one by one.
If you want to make your code behave how you are expecting you can wrap it into an async function
and then use the await
keyword to stop the execution of the syncronous code untile the promisses are resolved:
//async is actually creating a promise under the hood for you
async function imAsyncFunction () {
// await will make sure that before proceeding to the next
// synchronous instruction (the console.log) the promise chain is resolved
await Promise.resolve('333')
.then((res)=>{console.log(res);return new Promise((resolve,reject)=> {setTimeout(function(){console.log('Timeout');resolve(1);},10000);console.log('Something');})})
.then((res)=>{console.log(res);return new Promise((resolve,reject)=> {console.log('Something');resolve(2);})})
.then((res)=>{console.log(res);return new Promise((resolve,reject)=> {console.log('Something');resolve(3);})})
.then((res)=>{console.log(res);return new Promise((resolve,reject)=> {console.log('Something');resolve(4);})});
console.log("When?");
}
imAsyncFunction();
// the log produced will be:
// 333
// Something
// Timeout
// 1
// Something
// 2
// Something
// 3
// Something
// When?
Upvotes: 1
Reputation: 843
Good question. The answer is the Event Loop, which evaluates JavaScript. In short, there are microtasks and macrotasks. The console logs are macrotasks and the promises are microtasks. The Event Loop processes macrotasks first, then microtasks.
For a much more in depth explaination see: https://medium.com/javascript-in-plain-english/javascript-event-loop-y-promises-951ba6845899
There is a section with pretty much the same code in the question. Search for console.log('start');
to find it.
Upvotes: 2
Reputation: 13
Seems like you are new to Javascript. I was too and this messed with me a lot. console.log will always print first since it's is not inside the "then". Js will run the log asynchronously, which means it will not wait for the promise to finish. To solve this or better, to make sure this does not happen, use the log inside the .then or use Promise.all(promiseName).then(log here).
Hope I was able to be of help! This might help as well https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
PS: My first answer, please let me know if I did something wrong :p
Upvotes: 1