Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fromPromise incompatible with node v15 #268

Closed
supermacro opened this issue Apr 6, 2021 · 5 comments
Closed

fromPromise incompatible with node v15 #268

supermacro opened this issue Apr 6, 2021 · 5 comments

Comments

@supermacro
Copy link
Owner

It looks like as of node 15, unhandled promise rejections will terminate the Node process by default.

(node:28824) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Associated commit to Node: nodejs/node#33021

What does this mean for neverthrow?

It means that the current fromPromise API will need to change:

const typicalPromise = functionThatReturnsPromiseThatMightThrow()

// ** BOOM **
// The line below never gets called in Node v15 because of the way that node treats unahndled rejections now

return ResultAsync.fromPromise(typicalPromise, mapPromiseRejection)
@supermacro
Copy link
Owner Author

supermacro commented Apr 6, 2021

Probably the new API will need to be something like the following:

const resultAsync = ResultAsync.fromPromise(
  functionThatReturnsPromiseThatMightThrow,
  arguments,
  mapPromiseRejection,
)

Which allows neverthrow to .catch the promise rejection at the point in which it's created / returned:

fromPromise(fn, args, mapper) => {
  const handled = fn(args).catch(mapper)
}

Edit:

Another approach might be to enforce that the function argument is a "wrapper" / thunk:

fromPromise(
  () => functionThatReturnsPromiseThatMightThrow(arguments),
  mapPromiseRejection
)

@supermacro
Copy link
Owner Author

Curious to get your thoughts @paduc 🙂

@paduc
Copy link
Contributor

paduc commented Apr 7, 2021

Wow I didn't know such a huge change was on the horizon. I've read a bit about the new behaviour but it seems to me that you can still handle rejected promises higher in the stack, can't you ?
As I understand it, it only crashes when the unhandled exception bubbles up to the top and is never handled.

Have you tried it in Node 15 ?

@davazp
Copy link
Contributor

davazp commented Apr 11, 2021

Yeah I think @paduc is right.

The promise in that example would still be considered handled because fromPromise is actually handling it. It is only if there are no handlers when the promise rejects (not when defined), that the error bubbles up and kills the process.

This example shows it:

const {ResultAsync} = require('.');

async function f () {
  return Promise.reject(new Error('test'));
}

function main () {
  return ResultAsync.fromPromise(f(), ()=>0);
}

main().then(console.log);

setTimeout(()=>{
  console.log('done');
}, 3000);

This doesn't crash the process on node v15.

If you do not handle it, say, you replace return ResultAsync.fromPromise(f(), ()=>0); with return f(), then it will.

@supermacro
Copy link
Owner Author

Hmm, interesting. I hadn't gotten around to trying this out myself, but I figured that the act of not binding .catch on return Promise.reject(new Error('test')) would terminate the process.

Thanks for confirming @davazp!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants