Awaiting within an arrow function #7
Comments
[Edit: I completely didn't realize that exact thing I'm mentioning here is already mentioned in the main README of this spec.... duh... https://github.com/lukehoban/ecmascript-asyncawait#await-and-parallelism Probably isn't possible, but IMO it'd be awesome if async function renderChapters(urls) {
await* urls.map(getJSON).forEach(j => addToPage((await j).html));
} Where the I believe there was a thread about Just green-field dreaming. |
See @dherman's "Why Coroutines Won't Work For the Web". Note that this is equivalent to what you're doing here: calling a function (namely function doStuff(j) {
addToPage((await j).html);
}
async function renderChapters(urls) {
urls.map(getJSON).forEach(doStuff); // (1)
console.log("hi"); // (2)
} Here you're expecting the first line (1) to "block", preventing line (2) from executing until all the A version that could work would be something that async function renderChapters(urls) {
await asyncForEach(urls.map(getJSON), async (j) => addToPage((await j).html)));
} using the async arrow function syntax from this repo. |
I understand why the |
[Edit: later in this thread, thanks to @domenic, I realized why it wasn't "blocking" that I was assuming, but the implicit wrapping in
|
What would you think about let doStuff = j => addToPage((await j).html);
async function renderChapters(urls) {
urls.map(getJSON).forEach(doStuff); // (1)
console.log("hi"); // (2)
} ? It has the same problem but now we're using arrow functions. |
Remember that |
Tbh, I wouldn't mind I imagine your example would syntax error because Case closed, I see why it's not possible. It's a shame it isn't, though. |
I actually think the real problem with this assumption (or desire) is that you're calling So, if you had done: async function renderChapters(urls) {
urls.map(getJSON).forEach(async function(j) { addToPage((await j).html) });
} Then it's pretty clear that |
right, but That's why I used |
What would you expect this to do? function foo(x) {
setTimeout(() => return x + 1, 1000);
}
foo(1); // you would expect a return value of 2, somehow?? |
Yeah, as I said at the end of the comment, I realise now why it's not possible. |
So just to clarify, the original example (which doesn't work): async function renderChapters(urls) {
urls.map(getJSON).forEach(j => addToPage((await j).html));
} Could actually be written in one of three ways, with slightly differing results. If you write it like this: async function renderChapters(urls) {
for (let j of urls.map(getJSON)) {
addToPage((await j).html);
}
} Which is the closest to what was originally written, then all If you write it like this: async function renderChapters(urls) {
(await Promise.all(urls.map(getJSON))).forEach(j => addToPage(j.html));
} Then all getJSON operations will happen in parallel, and the application will wait until all requests are complete before adding them all to the page at once. Or if you write it like this: async function renderChapters(urls) {
await Promise.all(urls.map(getJSON).map(async j => addToPage((await j).html)));
} Then all getJSON operations will happen in parallel, and each object will be added to the page as it arrives (possibly out of order). Example here: http://www.es6fiddle.net/iftvukev/ (Or on Babel.) Edit: Replaced Edit 2: Added Babel mirror of example, clarify that original example is broken. |
await* is nonstandard syntax |
It is? Eh, well you can always just replace it with |
Yes, Babel is not standards compliant. |
Actually @domenic, Babel is spec complaint. The addition of something non standard doesn't make it not compliant, not unless it's explicitly forbidden. That doesn't matter anyway since it's already been removed for Babel 6 (babel/babel#2466) On Fri, Oct 16, 2015 at 4:40 PM, Domenic Denicola
|
To be pedantic, no implementation is completely standards compliant. @domenic's statement is not wrong but not saying much either :-P |
Sorry for reviving this thread all these months later. This thread is cited in multiple places as an explanation of why async arrow functions are impossible, but I'm not getting that. AFAICT, the point @domenic is making is that you are unleashing event loop Zalgo if you expect a synchronous operation to be able to invoke code which To be clear: So that's solved. What I don't get is how arrows relate to any of this. AFAICT the only concern there is that we have lexical this, but isn't that just as problematic as exposing any higher scope state? And even if it's a special kind of dangerous and horrible, isn't that just bad practice or 'considered dangerous' as opposed to logically impossible or semantically ambiguous? |
They're not.
IMO, they don't. I was incorrect earlier in the thread, for sure, but what I now realize is that @domenic's first comment was totally correct... Any kind of function, normal or arrow or otherwise, couldn't call If this thread is related to arrow functions particularly, it's that it highlights how easy it is to mistake an arrow function (conceptually) for just a block, in which you would expect to still be able to easily |
This conversation is mildly terrifying to me. Let's try not assume we are all are correct and end up in another Try to stay open-minded. Cheers. |
Assuming
getJSON
returns a promise for some JSON, does this work:Does the await within the arrow function halt the execution of both the
forEach
andrenderChapters
, or does it error because the arrow function is not an async function?If not, should we have a way to await to the parent async function?
The text was updated successfully, but these errors were encountered: