Reputation: 969
I am new to JS and was learning promises. So, let's say we have this code:
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000); // (*)
}).then(function(result) { // (**)
alert(result); // 1
return result * 2;
})
As you can see the code above, when promise is invoked, setTimeout is run via callback queue. The question is When setTimeOut is sent to a browser, will JS engine omit .then() and continues running the rest of the code until the promise resolves? Secondly, async/await example:
async function showAvatar() {
// read our JSON
let response = await fetch('/article/promise-chaining/user.json');
let user = await response.json();
// read github user
let githubResponse = await fetch(`https://api.github.com/users/${user.name}`);
let githubUser = await githubResponse.json();
// show the avatar
let img = document.createElement('img');
img.src = githubUser.avatar_url;
img.className = "promise-avatar-example";
document.body.append(img);
// wait 3 seconds
await new Promise((resolve, reject) => setTimeout(resolve, 3000));
img.remove();
return githubUser;
}
showAvatar();
When showAvatar function is called, JS engine will encounter let response = await fetch('/article/promise-chaining/user.json');
and sends fetch to the browser to handle. The second question is Will JS engine wait until fetch gets resolved or Will JS engine continue executing let user = await response.json();
and the rest of the code inside showAvatar function? If so, how can JS engine handle response.json() since response is not received? Hope you got my point))).
Upvotes: 1
Views: 491
Reputation: 1074138
Your first example works like this:
new Promise
runs, calling the function you pass it (the executor function) synchronouslysetTimeout
, passing in a function to call 1000ms later; the browser adds that to its list of pending timer callbacksnew Promise
returns the promisethen
is called, adding the function you pass into it to the promise's list of fulfillment handlers and creating a new promise (which your code doesn't use, so it gets thrown away).setTimeout
callback, which the JavaScript engine picks up and runsresolve
function to fulfill the promise with the value 1alert
and then returning result * 2
(which is 1 * 2
, which is 1
). That value is used to fulfill the promise created and thrown away in Step 4.Will JS engine wait until fetch gets resolved or Will JS engine continue executing
let user = await response.json();
...
It waits. The async
function is suspended at the await
in await fetch(/*...*/)
, waiting for the promise fetch
returned to settle. While it's suspended, the main JavaScript thread can do other things. Later, when the promise settles, the function is resumed and either the fulfillment value is assigned to response
(if the promise is fulfilled) or an exception will get thrown (if it is rejected).
More generally: async
functions are synchronous up until the first await
or return
in their code. At that point, they return their promise, which is settled later based on the remainder of the async
function's code.
In a comment you asked:
when async function is suspended at each await, will async function is removed from the call stack and is put back to the call stack again when the promise being awaited settles?
At a low level, yes; but to make debugging easier, a good, up-to-date JavaScript engine maintains an "async call stack" they use for error traces and such. For instance, if you run this on Chrome...
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function inner() {
await delay(80);
throw new Error("boom");
}
async function outer() {
await inner();
}
function wrapper() {
outer()
.then(result => {
console.log(result);
})
.catch(error => {
console.log(error.stack);
});
}
wrapper();
...the stack looks like this:
Error: boom at inner (https://stacksnippets.net/js:18:11) at async outer (https://stacksnippets.net/js:22:5)
Notice the "async" prior to "outer," and also notice that wrapper
isn't mentioned anywhere. wrapper
is done and has returned, but the async
functions were suspended and resumed.
Upvotes: 1