Thanks for your feedback! I really appreciate your perspective – and the video you recommended, which was amazing. I have a few follow-up questions for you, if you have the time.
I am not familiar with async generators. I'm digging into some documentation now. On first glance, async generators feel similar to how async-await behaved in my aforementioned example: the execution within the async function is paused until the Promise is resolved. Does the difference only lie with the typeof return value: Promise object vs Generator object?
If so, why is it preferred to make async-await behave like .then()? I figured async-await's rise in popularity is due to differences in behavior.
But async await automatically wraps every value it is used with, with a new promise, effectively creating a myriad of promises.
It was my understanding that async ensures that a function returns a promise by creating a new Promise only if a "thing" within the function is not a Promise. Am I missing something here when you caution about the "recipe for a blackout"?
It was my understanding that async ensures that a function returns a promise by creating a new Promise only if a "thing" within the function is not a Promise.
I think this is not exactly accurated. We are getting a promise, which resolves with the same value as the promise from the return statement but ...it is not true that the exact same object is returned, not even when there is already a promise, it is a new one.
const p = Promise.resolve('foo');
async function foo() {
return p;
}
p === foo(); // false
RE: async generators
This is somewhat an advanced topic that I have not used in a lot of projects, but it is very useful when handling multiple data emissions from an asynchronous operation/source (eg: continuous user interaction), kind of like streams. A good syntax to handle this is also the for await, it is better than awaiting inside of a loop, but unfortunately it doesn't fit quite well in every use case, hence the low popularity
forawait(letvalofmyIterator){// ...}
I can't remember some good code example, will have to look for some good examples/use-cases. I did use it in a small game I created using Pixi for the game loop or ticker or whatever you call that thing, but later replaced it with RxJS.
It was my understanding that async ensures that a function returns a promise by creating a new Promise only if a "thing" within the function is not a Promise.
You are correct, I forgot to include that detail.
But, like I said, it must be used with caution and one should not needlessly use it in front of everything.
RE: "recipe for a blackout"
I might have been a bit too dramatic there, but let me explain. See my note above for microtasks. it is difficult, but if someone managed to queue new microtasks (creating new Promises is one way of queuing a microtask) faster than the event loop can process them, then the loop gets stuck at the microtask queue and it will be stuck infinitely processing the microtasks.
Two important points here are:
I think it is impossible to completely halt the event loop at the microtask queue step, but the worst case scenario would be to have janky/laggy user experience even for very trivial tasks like reponding to click events, keyboard events, rendering DOM elements, etc.
async/await is not at fault here at all, this can be done with Promises and .then too, but it seems like it would go unnoticed easily with async/await as they can be used within loop bodies while .then can't be, atleast not the way you would expect it to behave (another reason I don't use await in loops)
I don't discourage the use of one asynchronous construct over the other, just that we should use things with caution, so that they don't backfire and atleast understand the basic working of anything before we use it
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
Guaurav Saini,
Thanks for your feedback! I really appreciate your perspective – and the video you recommended, which was amazing. I have a few follow-up questions for you, if you have the time.
I am not familiar with async generators. I'm digging into some documentation now. On first glance, async generators feel similar to how async-await behaved in my aforementioned example: the execution within the async function is paused until the Promise is resolved. Does the difference only lie with the typeof return value: Promise object vs Generator object?
If so, why is it preferred to make async-await behave like
.then()
? I figured async-await's rise in popularity is due to differences in behavior.It was my understanding that async ensures that a function returns a promise by creating a new Promise only if a "thing" within the function is not a Promise. Am I missing something here when you caution about the "recipe for a blackout"?
@kylejb @sainig Good post and solid dialog. Understanding & keeping promises are very important. 👍
It was my understanding that async ensures that a function returns a promise by creating a new Promise only if a "thing" within the function is not a Promise.
I think this is not exactly accurated. We are getting a promise, which resolves with the same value as the promise from the return statement but ...it is not true that the exact same object is returned, not even when there is already a promise, it is a new one.
const p = Promise.resolve('foo');
async function foo() {
return p;
}
p === foo(); // false
BTW the article is super nice, thank you
Oh, didn’t know it worked that way. Thanks for your input @naimadozodrac
Again as we find out, the devil lies in the details
RE: async generators
This is somewhat an advanced topic that I have not used in a lot of projects, but it is very useful when handling multiple data emissions from an asynchronous operation/source (eg: continuous user interaction), kind of like streams. A good syntax to handle this is also the for await, it is better than awaiting inside of a loop, but unfortunately it doesn't fit quite well in every use case, hence the low popularity
I can't remember some good code example, will have to look for some good examples/use-cases. I did use it in a small game I created using Pixi for the game loop or ticker or whatever you call that thing, but later replaced it with RxJS.
You are correct, I forgot to include that detail.
But, like I said, it must be used with caution and one should not needlessly use it in front of everything.
RE: "recipe for a blackout"
I might have been a bit too dramatic there, but let me explain. See my note above for microtasks. it is difficult, but if someone managed to queue new microtasks (creating new Promises is one way of queuing a microtask) faster than the event loop can process them, then the loop gets stuck at the microtask queue and it will be stuck infinitely processing the microtasks.
Two important points here are:
async/await
is not at fault here at all, this can be done with Promises and .then too, but it seems like it would go unnoticed easily withasync/await
as they can be used within loop bodies while.then
can't be, atleast not the way you would expect it to behave (another reason I don't use await in loops)I don't discourage the use of one asynchronous construct over the other, just that we should use things with caution, so that they don't backfire and atleast understand the basic working of anything before we use it