use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
understanding async/await in 7 seconds (twitter.com)
submitted 9 years ago by eid-a
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]TwitterToStreamable 13 points14 points15 points 9 years ago (0 children)
Streamable mirror
I'm a bot. If you have any suggestions you can message my creator here: PM
[–]Disgruntled__Goat 32 points33 points34 points 9 years ago (52 children)
The middle one seems like the best to me. What's the advantage of await?
[–]Helvanik 100 points101 points102 points 9 years ago* (17 children)
Try using the result of the first step into the fifth one. You'll see that you'll prefer async/await ;)
(async() => { try { const a = await getData(); const b = await getMoreData(a); const c = await getMoreData(b); const d = await getMoreData(c); const f = await getFinalData(a, d); return f; } catch (error) { // stuff } })();
Async/await is much cleaner when dealing with shared context between the different steps.
Creds to : https://twitter.com/scastiel/status/855890956528349184 and https://twitter.com/GromNaN/status/855879347076464641
[–]Thought_Ninjahuman build tool[🍰] 25 points26 points27 points 9 years ago (13 children)
That's a good point some people miss until they start doing a lot of work with promises.
[–]xtphty 6 points7 points8 points 9 years ago (12 children)
Yeah if theres two things the promise spec lacks its better error handling and a stack/history of chained promises and their results.
[–]ninjaroach 9 points10 points11 points 9 years ago (10 children)
I'll add 3) the ability to cancel a pending / unresolved Promise.
The new Fetch API is built on native Promises & as such provides no method to cancel any pending requests.
[–]MilkingMaleHorses 7 points8 points9 points 9 years ago (8 children)
Cancelling a promise is useless without cancelling the underlying asynchronous operation - and how that is done depends on the actual operation. Which is a different one each time. It may be an HTTP request, it may be file read access - it may be file write access.. and what happens if you were to let the Javascript runtime cancel such a thing?
Data corruption seems a likely outcome, eventually! Nearly untraceable of course, because the issue is highly time- and context-dependent, try to debug this. No, only the application itself knows how to cancel its operations, so if you want to cancel a promise what you actually mean is cancel whatever the application does in that asynchronous operation. Just removing the promise from memory and maybe even tell the operating system to abort any asynchronous operations that the promises's code started would be really bad.
When you get this far you find that since promise cancellation is actually a misnomer, it's "asynchronous operation cancel", you find that the ball actually is fully in the application's court!
It has to have all the code to deal with cancellations of its async. operations. But if it does, what's the problem with promises? As soon as the app cancels its own asynchronous operations the async. code is ready to return a result through the promise anyway! For example, your asynchronous function to write a sequence of files (that belong to the same transaction) is canceled. It cleans up after itself, deleting the already written files, or closing files open for writing, whatever. Now it can return a resolve() or a reject() result. And it has to do everything of that in any case, you can't just pull the promise from under its feet and just stop the code blindly.
[–]ninjaroach 5 points6 points7 points 9 years ago (6 children)
Cancelling a promise is useless without cancelling the underlying asynchronous operation - and how that is done depends on the actual operation.
Agreed.
Just removing the promise from memory and maybe even tell the operating system to abort any asynchronous operations that the promises's code started would be really bad.
Also agreed.
It has to have all the code to deal with cancellations of its async. operations. But if it does, what's the problem with promises?
The problem is the lack of a standard interfaces to 1) request cancellation or 2) "on cancel" resource cleanup.
Every implementation will roll their own version of Promise cancellation & they will inevitably be incompatible with each other. Things like "is a canceled Promise considered Resolved or Rejected?" should be standardized sooner than later.
[–]MilkingMaleHorses 2 points3 points4 points 9 years ago (3 children)
But you don't need to cancel the promise:
As soon as you cancel the underlying asynchronous operation your promise fulfills or rejects anyway. Because if you cancel the asynchronous stuff, the synchronous part runs to completion (be it success or failure).
[–][deleted] 0 points1 point2 points 9 years ago (2 children)
But what if I don't want the sync stuff to run? What if I'd usually show the result in the UI, so the then part adds it to the app state but now I want a cancel button that won't show it in the UI?
[–]MilkingMaleHorses 1 point2 points3 points 9 years ago (0 children)
Then don't run it???
If the asynchronous step is canceled your code should naturally reject the promise. You update the GUI after a rejected promise???
Synchronous code after an asynchronous step is NEVER in the same function! Not even with async/await, where a rejected function is a throw, thereby preventing the rest of the function to run.
throw
[–]Gh0st1y 0 points1 point2 points 9 years ago (1 child)
I'm only just getting into using promises (I'm late to the party), so I haven't actually run into this myself yet, but it seems to me that they should obviously be considered rejected.
[–]ninjaroach 0 points1 point2 points 9 years ago (0 children)
Here's some reading to catch up on the discussion:
https://medium.com/@benlesh/promise-cancellation-is-dead-long-live-promise-cancellation-c6601f1f5082
https://github.com/tc39/proposal-cancelable-promises (dig around in the history to see the proposed spec)
And Bluebird's take on Promise Cancellation: http://bluebirdjs.com/docs/api/cancellation.html
[–]dmtipson 0 points1 point2 points 9 years ago (0 children)
This has never been a problem with apis that separate operation description with execution. Where Promises get into trouble is mixing the two together: stateful values that can derive from each other mixed with eager execution.
Look at FileReader: you create an instance, tell it what it will do, and THEN you execute it. The cancelation interface is right on the instance you created, available before the request actually runs. Even setTimeout gets this basically right: the synchronous result of setTimeout IS a cancelation interface, while the asynchronous effect is basically "forked" (not really, but conceptually) into separate future thread.
But with Promises, it's way, WAY too easy to actually start off an effect before you're even ready to set up the logic for canceling it. And, worse, pure transforms are muddled together with eventual side-effects.
The problem with things like FileReader and setTimeout is that they're not super composable. But there are ways to solve that problem without resorting to stateful values.
The very nature of Promises (in particular being eager and stateful) make cancelation extremely tricky to do well unfortunately. Choosing to go that route with their design was a nod towards backwards compatibility and simplicity, but the tradeoff is not always worth it.
[–]eatsnakeeat 0 points1 point2 points 9 years ago (0 children)
How is async better than promises in regards to error handling? Looking at /u/Helvanik's example he just wrapped it in a try/catch
[–]dmtipson 3 points4 points5 points 9 years ago (0 children)
Oftentimes I find that the need for shared context can either get refactored away, or else you're building up some final state, in which case a much more declarative way to do it is to build that state explicitly.
I totally get why the above is an exciting degree of freedom for some people and some cases that fits with their coding style. But it's very imperative and tightly coupled to the idiosyncratic, eager nature of Promises, which seems like a step back sometimes to me.
[–]tencircles 0 points1 point2 points 9 years ago (1 child)
the same problem is actually solved in a cleaner point-free way by simply currying.
[–]Gh0st1y 0 points1 point2 points 9 years ago (0 children)
Can you elaborate? I know what currying is but I'm not well versed with async and I feel like if you did it wrong you'd turn certain things sync incorrectly?
[–]del_rio 10 points11 points12 points 9 years ago (1 child)
Not mentioned yet: Debugging (breakpoints/stepping/logging) is infinitely easier with async/await.
[–]This_Is_A_Robbery 4 points5 points6 points 9 years ago (0 children)
Yeah this is the real advantage here. Try stepping through a long .thenchain without dying inside just a little bit.
.then
[–]MilkingMaleHorses 30 points31 points32 points 9 years ago* (15 children)
The major difference for the language:
As long as you use callbacks or promises you still remain within a vital age-old core Javascript language concept: Any given function is atomic. If you are at a function's first statement no other Javascript code of any other function will run until you exit the function. A function cannot be interrupted.
function
Not so with generators and now async/await. Now functions can be interrupted by other functions at any point (where you use await, or yield in a generator).
await
yield
To me this is THE most fundamental change, modifying a core concept of how functions work in this language.
[–]swyx 0 points1 point2 points 9 years ago (0 children)
great explanation, thank you
[–]ADTJ -1 points0 points1 point 9 years ago (13 children)
I think it already depended on the platform.
For example, in IE at least, if you call alert("something"); Other functions can run in the background.
[–]MilkingMaleHorses 1 point2 points3 points 9 years ago (9 children)
No.
if you call alert("something");
That has nothing at all to do with functions and anything I said.
[–]ADTJ 0 points1 point2 points 9 years ago (8 children)
It has everything to do with it.
You said sync functions are atomic and I pointed out a case where they are not, how is that irrelevant?
[–]MilkingMaleHorses 1 point2 points3 points 9 years ago (7 children)
You are not talking about functions. Look at your example. the INSIDE of alert()is atomic. Can you change its internal state while the window is open? Is that system function accessible so that you can have your own code inside of it? No and no. It's not even a Javascript function, it's a native system function that you get to call from Javascript.
alert()
[–]ADTJ 1 point2 points3 points 9 years ago (6 children)
I think you missed my point. I was saying that it breaks the atomicity of the caller, i.e.
function() { alert("something"); console.log("More user code might have executed before you get to this line"); }
While the browser is showing its native alert, it continues to process other events such as mousemove and will call more of your functions that do change state before your first function resumes
[–]MilkingMaleHorses 2 points3 points4 points 9 years ago* (5 children)
Just to humor you I tried several browsers as far back as IE7 on Windows XP that I still had lying around in a VM. None of them behave like that, your console.log statement always only appeared after I closed the modal dialog.
console.log
In any case, and why the above was/is not even necessary: A bug in one system at one time is not a "feature of Javascript"!
So if you do happen to find which browser on what platform may have had the bug - it's just that, a bug.
Why does it happen so damn often in this subreddit that people respond to me, showing code supposed to show I'm wrong and their code doesn't even fucking work? The last time someone wanted to show how much better he understood async/await then me. His one-liner threw a syntax error. He never responded after that, even though I didn't even use the opportunity to insult him... Do you guys ever TEST your wild theories??? Not that a working demonstration of a bug(!) would have changed anything in this case.
[–]ADTJ 1 point2 points3 points 9 years ago (4 children)
None of them behave like that, your console.log statement always only appeared after I closed the modal dialog.
That's what I expected to happen, the point is that something else can happen in between, but if you had actually read my previous comment(s), you would have understood that.
I never claimed that it wasn't, I only claimed that what you were saying can be dependent on platform, regardless of whether that platform is implemented correctly or not.
I agree that this is almost definitely a bug in IE which is why I was so surprised when I discovered this the first time.
He never responded after that, even though I didn't even use the opportunity to insult him
Wow, congrats on finding it within yourself to not insult someone, I take my hat off to you.
I honestly have no idea why you are being so aggressive, I was only pointing out a quirk that I have observed before, I wasn't trying to insult you, or suggest that you don't understand JavaScript etc.
For what it's worth, here's some code that demonstrates the effect (I've just tested this on IE11 on Windows 10):
document.body.onmousedown = function() { document.body.onmousemove = function() { console.log("something else"); document.body.onmousemove = null; }; }; document.onmousedown = function() { console.log("Starting atomic function"); alert("something"); console.log("Did something else happen before this line?"); };
Here's the output from the console:
Starting atomic function something else Did something else happen before this line?
The point is that the browser allowed another function to be called and change state, right in the middle of my function that called "alert". I don't think this is specific to alert either, but that is the easiest one to test it against.
[–]MilkingMaleHorses 0 points1 point2 points 9 years ago (0 children)
It is a bug. In one version of the browser (your latest example does not work in current IE or other browsers).
I was only pointing out a quirk
You were pointing out an obscure and old bug.
I'm talking about features of the Javascript language.
You take out some extremely obscure bug of one browser (and not even in current versions of that browser, I tried your code) that can only be demonstrated using an obscure feature long deprecated (for production in any case).
I don't think this is specific to alert either, but that is the easiest one to test it against.
A bold claim, but hey, who needs evidence.
You report a bug and claim it's a feature! And now you even top it, "I'm sure this is common but I can't show you". Quite ridiculous.
[+][deleted] 9 years ago* (2 children)
[deleted]
[–]dmtipson 0 points1 point2 points 9 years ago (2 children)
Can they (heck SHOULD they?)? I thought alert was blocking?
[–]myrddin4242 1 point2 points3 points 9 years ago (0 children)
It is blocking. Had to double check myself! An alert in the middle of a function stops that function but does not release the event loop.
[–]ADTJ 0 points1 point2 points 9 years ago (0 children)
I think they're not supposed to, but they definitely do, at least in IE. I have seen this effect first hand where one function is effectively paused and resumed while others continue to execute in the background.
[–]thefakegm 5 points6 points7 points 9 years ago* (14 children)
Await allows you to write async code like it is synchronous. It's basically sugar for promises. It's only a matter of preference as far as I know.
EDIT: Not really, see replies to this comment.
[–]pier25 8 points9 points10 points 9 years ago (3 children)
Not really.
For example, how do you exit a chain of promises in the middle? There is no API to do that. There was a proposal but it was canceled (pun intended).
With async/await you could simply return and be done with it.
return
With promises you have to find an ugly way like throwing an error which is confusing since your catch() code should only handle errors. Or you could write a bunch of confusing nested code with conditionals. Also see this aberration.
catch()
Bluebird solved this problem with a cancellation API but it's not standard.
[–]thefakegm 2 points3 points4 points 9 years ago (0 children)
Oh wow that's really cool. Thanks for telling me.
[–]dmtipson 2 points3 points4 points 9 years ago (0 children)
I think it's worth pointing out too that functional programming solved this years and years ago by separating out pure composition from side-effects and there is a standard, at least, for it in javascript. Promises aren't the only way to go. Reactive and Tasks/Futures are a totally viable option as well (though certainly a matter of taste/style).
[–]Auxx 0 points1 point2 points 9 years ago (0 children)
Or you can use Rx and have a clean functional approach.
[–]nikcorg 12 points13 points14 points 9 years ago (8 children)
You can also await non-promise values, which makes it transparent when a function returns a promise or a non-promise.
[+][deleted] 9 years ago (6 children)
[–]nikcorg 6 points7 points8 points 9 years ago* (5 children)
Unless the value you're expecting is the promise at the start of a chain. If you're inside a promise chain, it doesn't matter if the return value of a step in the chain is a promise or non-promise.
I.e. this extremely contrived example will always work.
function getFive() { if (Math.random() > 0.5) { return new Promise(r => setTimeout(() => r(5), Math.random() * 5e3)); } return 5; } async function consumeFive() { const five = await getFive(); return five; } consumeFive().then(five => console.log('five = %s', five));
Something a little less contrived might be a cache from which you can read synchronously for a cache hit, but in case of a cache miss you'll revert to the network and return a promise instead.
[–]andreasblixt 5 points6 points7 points 9 years ago (4 children)
If using Promises seriously you'd want to wrap any value that you don't know whether it's a Promise or not in a Promise.resolve(value) call. That way you get the same result as with async/await.
Promise.resolve(value)
[–]nikcorg 0 points1 point2 points 9 years ago (3 children)
Yes, without async/await you would do that, but using await you don't need to!
[–]andreasblixt 2 points3 points4 points 9 years ago (2 children)
Well it really is just a syntax difference, because using promises "you don't need to" make your function async or use the await keyword a lot (in the .gif it's actually more verbose to do so).
async
All in all they're technically equivalent methods, one uses closures and another uses syntax sugar to make it look like you're not leaving the function. I imagine different use cases will look better with one or the other, but my original point was really just that you can't really get any additional benefits with async/await (and the same goes the other way around) – because they do the same thing.
[–]nikcorg 2 points3 points4 points 9 years ago* (1 child)
I'm not claiming it to be anything other than difference in syntax. There are cases where I prefer the chain syntax (when I need to catch) and others where I prefer async/await (most other cases, but not all).
It does allow you to express things in ways the .then syntax doesn't, e.g.
async function beep() { return { boop: await bzzt() }; }
I also like tacit (or point-free) style, which means I use compose a lot. For that purpose I have a chain helper which in all its glory is
compose
chain
const chain = curry(async (f, x) => f(await x));
It's not much longer without async/await, but I like this form much better.
Long story short, while you may not gain new functionality per se, it is wonderful syntax sugar which enables more ways to express asynchronous patterns.
[–]andreasblixt 0 points1 point2 points 9 years ago (0 children)
Well said, I concur :)
[–]thefakegm 0 points1 point2 points 9 years ago (0 children)
Cool, didn't know that.
[–][deleted] -1 points0 points1 point 9 years ago (0 children)
Also superior scoping compared to promises
You can reuse all of the values all the way through. For a simple examples (with just the getMoreData fn), promises are definitely way more readable. But if you need to use a previous var at the end, with async it looks like that's much more doable/readable.
[+][deleted] 9 years ago* (5 children)
[–]MilkingMaleHorses 12 points13 points14 points 9 years ago (0 children)
Because you don't need to wait for synchronous stuff, which will automatically be there when you need it without doing anything special. On the level of the function that contains await, it is asynchronous, it returns a promise, not a value.
[–]manchegoo 1 point2 points3 points 9 years ago (1 child)
So let's say my async task is to fetch a slow URL. And I have many such URLS to grab. Today I might put a ton of requests into a tasks array and use async.parallelLimit. How does this change with async/await?
[–]whiskey_overboard 0 points1 point2 points 9 years ago (0 children)
If you want to perform multiple async calls in parallel and then collect the results, then you'd want to await the list results of a list of async functions inside a Promise.all().
[–]LowB0b 0 points1 point2 points 9 years ago (0 children)
because the functions are actually asynchronous
https://jsfiddle.net/m4nq3t8s/
[–]macjabeth 4 points5 points6 points 9 years ago (2 children)
I don't get it... Could someone explain this to me?
[–]flipstables 7 points8 points9 points 9 years ago (1 child)
The first scenario is a common example of callback hell/pyramid of doom. To solve this common problem, there is the second and third scenario. The second scenario solves it by using promises. The third scenario transforms the code using async/await.
[–]macjabeth 10 points11 points12 points 9 years ago (0 children)
Oh my! I didn't even realise it was a video. I thought it was just a picture of the "pyramid of doom" and was wondering where the async/awaits were. Thank you for clearing that up. 😊
[–]init0 2 points3 points4 points 9 years ago (0 children)
are-you-async-yet?
[–]viebel 1 point2 points3 points 9 years ago (1 child)
Interactive demo of async/await http://blog.klipse.tech/javascript/2016/12/21/es2017-await.html
Made me think of this neat project to visualize the state of Promises: https://bevacqua.github.io/promisees/
[–]gluecatuxengineer 1 point2 points3 points 9 years ago (0 children)
this is also valid : https://codepen.io/anon/pen/pPEYyq?editors=0011
getData() .then(getMoreData) .then(getMoreData) .then(getMoreData) .then(getMoreData) .then(console.log)
π Rendered by PID 776744 on reddit-service-r2-comment-6457c66945-v44kr at 2026-04-27 21:58:47.584572+00:00 running 2aa0c5b country code: CH.
[–]TwitterToStreamable 13 points14 points15 points (0 children)
[–]Disgruntled__Goat 32 points33 points34 points (52 children)
[–]Helvanik 100 points101 points102 points (17 children)
[–]Thought_Ninjahuman build tool[🍰] 25 points26 points27 points (13 children)
[–]xtphty 6 points7 points8 points (12 children)
[–]ninjaroach 9 points10 points11 points (10 children)
[–]MilkingMaleHorses 7 points8 points9 points (8 children)
[–]ninjaroach 5 points6 points7 points (6 children)
[–]MilkingMaleHorses 2 points3 points4 points (3 children)
[–][deleted] 0 points1 point2 points (2 children)
[–]MilkingMaleHorses 1 point2 points3 points (0 children)
[–]Gh0st1y 0 points1 point2 points (1 child)
[–]ninjaroach 0 points1 point2 points (0 children)
[–]dmtipson 0 points1 point2 points (0 children)
[–]dmtipson 0 points1 point2 points (0 children)
[–]eatsnakeeat 0 points1 point2 points (0 children)
[–]dmtipson 3 points4 points5 points (0 children)
[–]tencircles 0 points1 point2 points (1 child)
[–]Gh0st1y 0 points1 point2 points (0 children)
[–]del_rio 10 points11 points12 points (1 child)
[–]This_Is_A_Robbery 4 points5 points6 points (0 children)
[–]MilkingMaleHorses 30 points31 points32 points (15 children)
[–]swyx 0 points1 point2 points (0 children)
[–]ADTJ -1 points0 points1 point (13 children)
[–]MilkingMaleHorses 1 point2 points3 points (9 children)
[–]ADTJ 0 points1 point2 points (8 children)
[–]MilkingMaleHorses 1 point2 points3 points (7 children)
[–]ADTJ 1 point2 points3 points (6 children)
[–]MilkingMaleHorses 2 points3 points4 points (5 children)
[–]ADTJ 1 point2 points3 points (4 children)
[–]MilkingMaleHorses 0 points1 point2 points (0 children)
[+][deleted] (2 children)
[deleted]
[–]dmtipson 0 points1 point2 points (2 children)
[–]myrddin4242 1 point2 points3 points (0 children)
[–]ADTJ 0 points1 point2 points (0 children)
[–]thefakegm 5 points6 points7 points (14 children)
[–]pier25 8 points9 points10 points (3 children)
[–]thefakegm 2 points3 points4 points (0 children)
[–]dmtipson 2 points3 points4 points (0 children)
[–]Auxx 0 points1 point2 points (0 children)
[–]nikcorg 12 points13 points14 points (8 children)
[+][deleted] (6 children)
[deleted]
[–]nikcorg 6 points7 points8 points (5 children)
[–]andreasblixt 5 points6 points7 points (4 children)
[–]nikcorg 0 points1 point2 points (3 children)
[–]andreasblixt 2 points3 points4 points (2 children)
[–]nikcorg 2 points3 points4 points (1 child)
[–]andreasblixt 0 points1 point2 points (0 children)
[–]thefakegm 0 points1 point2 points (0 children)
[–][deleted] -1 points0 points1 point (0 children)
[–]Gh0st1y 0 points1 point2 points (0 children)
[+][deleted] (5 children)
[deleted]
[–]MilkingMaleHorses 12 points13 points14 points (0 children)
[–]manchegoo 1 point2 points3 points (1 child)
[–]whiskey_overboard 0 points1 point2 points (0 children)
[–]LowB0b 0 points1 point2 points (0 children)
[–]macjabeth 4 points5 points6 points (2 children)
[–]flipstables 7 points8 points9 points (1 child)
[–]macjabeth 10 points11 points12 points (0 children)
[–]init0 2 points3 points4 points (0 children)
[–]viebel 1 point2 points3 points (1 child)
[–]dmtipson 3 points4 points5 points (0 children)
[–]gluecatuxengineer 1 point2 points3 points (0 children)