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);
});