Home > database >  How is async/await working in this code snippet?
How is async/await working in this code snippet?

Time:10-11

I am reading MDN on how async code works with javascript. They propose this example:

async function myFetch() {
  let response = await fetch('coffee.jpg');

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  let myBlob = await response.blob();

  let objectURL = URL.createObjectURL(myBlob);
  let image = document.createElement('img');
  image.src = objectURL;
  document.body.appendChild(image);
}

myFetch()
.catch(e => {
  console.log('There has been a problem with your fetch operation: '   e.message);
});

Function myFetch() is defined and then it's called in a Promise-way style. How exactly is the function executed? It's an async function, so I assume that it's given to some thread to execute without interfering with the single thread that runs Javascript code? Also in the docs they said await is stoping the code on that line until completion? So the function can't be executed by the main application thread because then it's not async code anymore? So those are my issues and I wanna be sure I understand this mechanism before I start writing actual code. Thank you!

CodePudding user response:

using async/await is pretty similar to using promises, async function returns a Promise for you, that promise can have one of three statuses (Pending, Fulfilled, Rejected)

By default, the returned Promise is Fulfilled (Resolved) similar to:

Promise.resolve().then(_ => { //... })

using await, the Promise will be pending on the code that you are awaiting for

new Promise((resolve, reject) => {
  // ... some tasks here
  resolve(resolvedData);
})
.then(_ => { //... })

when an error is thrown, automatically or manually, the Promise will be rejected

new Promise((resolve, reject) => {
  reject(); // Reject manually
})
.then(_ => { })
.catch(e => { //... })

By default, all JavaScript code is executing within the main thread, which is the only thread that JavaScript has

Look at the following example:

async function c() {
    const t = await Array.from(Array(100000000).keys())
}
c().then(t => console.log('I am waiting for the Promise to be fulfilled!'))
console.log('Hey, I don\'t need to wait');

You will get the expected output:

"Hey, I don't need to wait"
"I am waiting for the Promise to be fulfilled!"

but both logs are waiting for filling this 100000000 array, so the main thread now is busy and blocked to complete this task first, JavaScript itself can't help with this case,

Another Example:

async function c() {
    const t = await fetch('https://jsonplaceholder.typicode.com/photos')
}
c().then(_ => console.log('I am waiting for the Promise to be fulfilled!'))
console.log('Hey, I don\'t need to wait');

Here you'll get the same result, but Hey, I don't need to wait will be logged immediately, and only I am waiting for the Promise to be fulfilled! will be waiting,

Why? here we need to refer to few important things to read more about (Event Loop, Call Stack, Micro & Macro tasks )

In simple words, the promise behaves the same, it's pending on something, and the first console log in the code is awaiting the promise to be fulfilled,

the difference is that the task that we are waiting for to have a fulfilled promise now is not thread-blocking, it is not controlled by JavaScript itself

the fetching task is managed by an external API that is observed by the Event loop, in this case, the call stack will not be busy, and the main JavaScript thread can continue working, the code that will resolve the promise is added to a queue and will be pushed to the call stack by the Event loop when the fetching task is done by the external API

CodePudding user response:

Function myFetch() is defined and then it's called in a Promise-way style.

It's called like any other function. All async functions wrap the return value in a Promise, thus there are then, catch and finally methods available.

How exactly is the function executed?

Using () like any other function.

It's an async function, so I assume that it's given to some thread to execute without interfering with the single thread that runs Javascript code?

There is no need to have it run on some other thread. As you say, JavaScript execution happens in a single thread.

Also in the docs they said await is stoping the code on that line until completion?

Yes, in that async function.

So the function can't be executed by the main application thread because then it's not async code anymore?

There doesn't have to be any threading involved. It is only the fetch and blob operations that are performed asynchronously. While those operations are being awaited, the event loop and the execution of code outside the async function will continue. If you have code below the call to myFetch then that will be executed while the fetch is being awaited, unless you await the call to myFetch itself.

async and await are syntactic sugar on top of Promises, so effectively your code is doing the following:

fetch('coffee.jpg').then(response => {
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
  response.blob().then(myBlob => {
    let objectURL = URL.createObjectURL(myBlob);
    let image = document.createElement('img');
    image.src = objectURL;
    document.body.appendChild(image);
  });
}).catch(e => {
  console.log('There has been a problem with your fetch operation: '   e.message);
});
  • Related