question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Better integration with async/await

See original GitHub issue

Hi there,

I know that this has come up a few times in a few different ways, but I’m coming at it from a different point of view.

One of the major benefits of async/await is that it helps to make the code more readable. You get to write more procedural code that is more obvious to read and maintain, instead of complicated call stacks.

For example, the following are the same:

return doSomething()
    .then(result => doSomethingElse(result))
    .then(next => next.abc);
// -----
const result = await doSomething();
const next = await doSomethingElse(result);
return next.abc;

The second of which is much more obvious for someone to follow.

Neverthrow is awesome, but the fact that it not only doesn’t work with async/await but also doesn’t work well with Promise makes it awkward to use. If I start to use it in a call stack I end up having to use it throughout the entire call stack, or else using things like _unsafeUnwrap() to escape from it.

This means that it’s more difficult to introduce into a project. I have to start from the outside and work in, because I can’t easily convert a layer until all of the callers are already expecting ResultAsync objects to be returned. And this is especially big if you consider infrastructure-level layers. For example, if I were to update a database layer to use neverthrow instead of exceptions then I’ve got to update the entire application in order to make that work!

The frustrating thing is that Promise<Result<T, E>> almost works fine. It’s just the fact that the various methods on it - map, andThen, etc - don’t allow for async methods that cause problems.

For example, the following would - to me, at least - be a much easier to understand and maintain alternative:

return doSomething() // function doSomething() : ResultAsync<string, Error>
    .andThen(doSomethingElse) // function doSomethingElse(string) : ResultAsync<foo, Error>
    .map(next => next.abc());
// -----
const result = await doSomething(); // async function doSomething() : Promise<Result<string, Error>>
const next = await result.andThenAsync(doSomethingElse); // async function doSomethingElse(string) : Promise<Result<foo, Error>>
return await next.mapAsync(n => n.abc());

where in this case the andThenAsync and mapAsync functions take async functions and return Promise<Result<T, E>> instead. And, importantly, it would mean that I can replace any individual part of the call chain with neverthrow without needing to replace all of it.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:10 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
paduccommented, Sep 17, 2021

I was using async on the function so that I can use await within it. And I suspect that in reality, I need to use fromPromise inside it instead. (This exact function is using Got.post() to make HTTP requests, so was await-ing on the results of that)

Yes, either you want to stick with async/await inside the method and maybe return a Promise<Result> or you can wrap any lower-level async code inside a fromPromise wrapper (which lets you type the error). I would do the latter.

As for now using result.value - that was just an oversight. I’d not realised it was there! Partly because VSCode/TS is “clever” and it’s not even an autocomplete option until after you’ve done the result.isErr() bit.

All good !

Cheers

2reactions
sazzercommented, Sep 17, 2021

I was using async on the function so that I can use await within it. And I suspect that in reality, I need to use fromPromise inside it instead. (This exact function is using Got.post() to make HTTP requests, so was await-ing on the results of that)

As for now using result.value - that was just an oversight. I’d not realised it was there! Partly because VSCode/TS is “clever” and it’s not even an autocomplete option until after you’ve done the result.isErr() bit.

Cheers

Read more comments on GitHub >

github_iconTop Results From Across the Web

Effortless Concurrency in Swift with Async/Await
Integrating callback-based asynchronous functions with async/await. While using async/await is clearly better, if you have a project full of ...
Read more >
Asynchronous Javascript: From Promises to Async/Await
This post dives into asynchronous programming in Javascript and discusses async/await vs promises.
Read more >
Integrating async await into synchronous methods
If I go async await all the way down, what do I do with the methods higher up the stack, like my WebApi...
Read more >
Async and Await - LearnHowToProgram.com
An async function allows us to write asynchronous code as if it were synchronous. This can make our code more concise. And while...
Read more >
Long Story Short: Async/Await Best Practices in .NET - Medium
Async /Await makes deceptively simple to implement asynchronous code, and removes the programmer from having to deal with the details of handling ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found