Live data from Hacker News

Mistakes we make using JavaScript Promises

betamark.com

11–20 of 60 posts

Re: Mistakes we make using JavaScript Promises

#12
post #10

Earlier quoted context omitted.

I feel it should have been called out explicitly when introducing await, because the 'clean' solution in async/await code is to call each async function and then await the results where you need them - which is a pattern he doesn't hint at at all.

I think there is a danger in that approach: if you forget to await, errors are silently ignored. You can also await a Promise.all, which is reasonably good enough if you do depend on all of the results to do anything meaningful anyways.

If you need you can name your intermediate results fooPromise or something else to make it obvious that it isn't meant to be used directly.

The async article linked from this article has a toy example for this concept where the result is unused, but most of the time you would be passing the result somewhere. If you were using typescript it could fail at compile time when you try to pass a promise instead of the expected type. Even if you're not, you should notice it never work in your tests.

Re: Mistakes we make using JavaScript Promises

#13
One thing I realized about async/await is that it removes the ability to use the synchronous continuation of an async function call. In return, it makes its asynchronous continuation feel synchronous. Technically, that's less power, but I realized that's almost always a good thing.

Re: Mistakes we make using JavaScript Promises

#14

Hopefully with async/await we can all put this behind us. In my own projects, async/await has made improved readbility and reduced errors.

I have found cases in which async/await won’t cut it quite as cleanly as “return new Promise”. AWS Cognito’s API has functions that take an object parameter with properties onSuccess and onFailure. If these functions are being called with programmatically created values within promises you can use “await new Promise” but that means declaring an additional async/await function (and therefore a promise) that resolves with the resolution of another promise. When you are explicitly defining all of your operations in TypeScript you notice these anti-patterns. Of course you could also declare these functions elsewhere and use function parameters instead of scoped variables. In my opinion the best solution is the one that is most justifiable when described to an outsider while walking through the code so I sometimes feel grateful for the freedom to choose my promise implementations on a case-by-case basis. When the relevant code is entirely my own, however, async/await is the most elegant.

Async/await is pure syntactic sugar and should not reduce errors unless the Promise syntax was implemented incorrectly.

Re: Mistakes we make using JavaScript Promises

#15
With respect to Promise.all:

> In this example, both promises will be processed asynchronously and only when both of them are resolved, we handle the result.

While that is true if all the promises resolve successfully, if any of the promises get rejected the catch block gets executed as soon as the first rejection occurs. Beware of that behavior, as if you're not aware of it it can leave your system in a bad state (speaking from experience, of course :)

Re: Mistakes we make using JavaScript Promises

#16

One thing I realized about async/await is that it removes the ability to use the synchronous continuation of an async function call. In return, it makes its asynchronous continuation feel synchronous. Technically, that's less power, but I realized that's almost always a good thing.

I don't understand what you're saying here. An async function just returns a Promise, that's it. You don't have to await on it immediately - you could just as easily assign it to a variable and await on it some time later.

Re: Mistakes we make using JavaScript Promises

#17

Hopefully with async/await we can all put this behind us. In my own projects, async/await has made improved readbility and reduced errors.

async/await helps a lot, but there are still a few common errors with them...

1) Not calling promises in parallel. Easy to do because it's impossible to run them in parallel with just "await", need to use Promise.all() or something.

2) Forgetting to write "await". If you try to use the return value then now you have a Promise object instead of the actual value. But the worst is when the code doesn't use the return value. Then it has a really subtle race condition that's hard to find. Or if the promise has any errors, then you might get the dreaded "Unhandled promise rejection" with a useless stack trace, and you might need to search the entire codebase to find where it happened.

Re: Mistakes we make using JavaScript Promises

#18
post #10

Earlier quoted context omitted.

I think there is a danger in that approach: if you forget to await, errors are silently ignored. You can also await a Promise.all, which is reasonably good enough if you do depend on all of the results to do anything meaningful anyways.

If you need you can name your intermediate results fooPromise or something else to make it obvious that it isn't meant to be used directly. The async article linked from this article has a toy example for this concept where the result is unused, but most of the time you would be passing the result somewhere. If you were using typescript it could fail at compile time when you try to pass a promise instead of the expec…

Sorry, by forget to await, I mean you call an async function but then don’t ever actually use the result. TypeScript can also diagnose that one by illuminating unused variables.

Still, I think it is easiest to never mess up if you await as soon as you have a promise value. In many common cases this is easy enough.

Re: Mistakes we make using JavaScript Promises

#19

Are these "common" mistakes? With basic understanding of Promises, these mistakes shouldn't happen. Also I believe #1 is wrong when using async/await.

Some older libraries will still be callback driven, and one important thing is always resolving or rejecting promise.

Re: Mistakes we make using JavaScript Promises

#20

Hopefully with async/await we can all put this behind us. In my own projects, async/await has made improved readbility and reduced errors.

I have found cases in which async/await won’t cut it quite as cleanly as “return new Promise”. AWS Cognito’s API has functions that take an object parameter with properties onSuccess and onFailure. If these functions are being called with programmatically created values within promises you can use “await new Promise” but that means declaring an additional async/await function (and therefore a promise) that resolves w…

I'm not sure I fully understand. Interoperability is as simple as wrapping the non-standard API, no? This way you have a standard calling style in your code. It's not a weakness of async/await that some libraries don't have promise friendly APIs.
Post reply on HN