Live data from Hacker News

Mistakes we make using JavaScript Promises

betamark.com

41–50 of 60 posts

Re: Mistakes we make using JavaScript Promises

#42

_any_ function that returns a promise should have the `async` modifier - even if `await` isn't used. A function may return a promise or throw an exception. An `async` function may only return a promise. async functions cannot throw exceptions. ``` // This code sucks but you might have to write it if `get` isn't an async function. try { get().catch(_ => /* handle async errors /) } catch { / handle sync errors */ } ```

HN does not support the Markdown syntax for code blocks. You need to indent all lines by two spaces to get a code block.

Re: Mistakes we make using JavaScript Promises

#43

Earlier quoted context omitted.

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.

The API in this example is promise-friendly, it is just intended for callback syntax; providing two situational callback options. This an implementation issue. Of course you can wrap the non-conformant external code but in this case that means accepting anti-patterns in order to gain the benefit of syntactic sugar. Writing API wrappers that do nothing more than wrap traditional Promise callback code as a rule is a po…

Async/await is inherently better than other syntax though, for a number of reasons, and the interpreter does indeed know the difference. If anything the interpreter knows much more about your intent, rather than “oh this function takes a `callback` parameter that’s a function” and can optimize based on that info.

Re: Mistakes we make using JavaScript Promises

#44

This "solution" given here has a syntax error since you don't have access to `user` within the second then() callback: get("http://data.com/user") .then(user => get("http://data.com/location" + user.id)) .then(location => createEntry(user, location)) .then(response => { // handle response }).catch(err => { // handle failure }); Instead, back before async/await made things easier this nested pattern was used (notice t…

Thanks for the feedback! I update the post with your corrections

Re: Mistakes we make using JavaScript Promises

#45
post #43

Earlier quoted context omitted.

The API in this example is promise-friendly, it is just intended for callback syntax; providing two situational callback options. This an implementation issue. Of course you can wrap the non-conformant external code but in this case that means accepting anti-patterns in order to gain the benefit of syntactic sugar. Writing API wrappers that do nothing more than wrap traditional Promise callback code as a rule is a po…

Async/await is inherently better than other syntax though, for a number of reasons, and the interpreter does indeed know the difference. If anything the interpreter knows much more about your intent, rather than “oh this function takes a `callback` parameter that’s a function” and can optimize based on that info.

It is not better, the two have different use cases. If you are using setTimeout to delay then you need a callback. Being so obsessed with the syntax that you right your code twice is the only wrong solution. While the AsyncFunction is used only by async statements and expression it uses Promise under the hood. In terms of performance it is not a good idea to make assumptions like that, performance can only be determined by testing.

Re: Mistakes we make using JavaScript Promises

#46
post #27

This "solution" given here has a syntax error since you don't have access to `user` within the second then() callback: get("http://data.com/user") .then(user => get("http://data.com/location" + user.id)) .then(location => createEntry(user, location)) .then(response => { // handle response }).catch(err => { // handle failure }); Instead, back before async/await made things easier this nested pattern was used (notice t…

Instead of subtle nesting, I would have passed through the user as part of the result of the second promise. get('//data.com/user) .then(user => resolve({user, location: get('//data.com/user')})) .then(({user, location}) => createEntry(user, location)) .then(response => { // handle response }).catch(err => { // handle failure }); Async/await is much cleaner now though.

I affably don’t know how anyone considers the .then syntax to be any better than the original callback hell version. Especially if you want your error handlers to be unique and to affect the flow. Sorry but the common shared catch at the end doesn’t usually suffice in the code I write.

I find the async/await form he alludes to at the end to be the only form that improves upon the original callback version.

Re: Mistakes we make using JavaScript Promises

#47

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 va…

Also sometime I don’t want promise.all but I do want them in parallel somewhat but with a max concurrency setting. Still have to pull out the old async.js package for that one and use it’s maxLimit.

Re: Mistakes we make using JavaScript Promises

#48

_any_ function that returns a promise should have the `async` modifier - even if `await` isn't used. A function may return a promise or throw an exception. An `async` function may only return a promise. async functions cannot throw exceptions. ``` // This code sucks but you might have to write it if `get` isn't an async function. try { get().catch(_ => /* handle async errors /) } catch { / handle sync errors */ } ```

Interesting about adding async. I actually didn’t know it eliminated the possibility of it throwing an error. What happens if it explicitly throws an error?

Re: Mistakes we make using JavaScript Promises

#49
post #34

Earlier quoted context omitted.

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 va…

It's easy to run tasks in parallel with just "await". Just start your tasks without await, store the promise in a variable, and then use await later when you actually need the value.

That's fine, but you'll still only be able to block on one promise at a time. If you want to wait until all promises have resolved you still have to use Promise. all.

Re: Mistakes we make using JavaScript Promises

#50
post #27

Earlier quoted context omitted.

Instead of subtle nesting, I would have passed through the user as part of the result of the second promise. get('//data.com/user) .then(user => resolve({user, location: get('//data.com/user')})) .then(({user, location}) => createEntry(user, location)) .then(response => { // handle response }).catch(err => { // handle failure }); Async/await is much cleaner now though.

I affably don’t know how anyone considers the .then syntax to be any better than the original callback hell version. Especially if you want your error handlers to be unique and to affect the flow. Sorry but the common shared catch at the end doesn’t usually suffice in the code I write. I find the async/await form he alludes to at the end to be the only form that improves upon the original callback version.

Agree. Async/await and promises get overly complex and riddled with conceptual challenges in anything but the most basic examples. I finally rolled my own async job queue library instead (using .then, granted). A few hundred loc, but conceptually clear, no callback hell, a tiny bit more verbose, but full control over error handling in each callback. Such a relief.
Post reply on HN