Promise.catch is swallowing errors

I've done a lot of async coding in Node.js with callbacks and the excellent async library which works great. I'm trying to use a module that uses promises but I'm running into a problem where any errors thrown AFTER the promise are still bubbled up and caught by the promise error handler.

This makes it very difficult to debug errors as I have no idea where they will pop up and they can't be thrown and don't crash the app.

Example code below; all I want to do is to exit the promise chain and leave it behind once it has been resolved, rather than it catching all subsequent errors that aren't anything to do with it.

function one (input, callback) {

  doSomeAsyncWork(input)
  .then(function (result) {
    return callback(null, result);
  })
  .catch(function (err) {
    logError(err);
    return callback(err);
  });

}

function two (err, result) {

  if (err) { ... }

  var x = callAMethodThatThrows();
  ...

}

one('abc', two);

In this example, the method callAMethodThatThrows() throws an error, which gets bubbled up to the promise catch() block. This prevents the app from crashing and leaves it in an unknown state.

Any advice would be really appreciated, thanks.

Answers


Yes, sorry about that - we're getting to fixing(1) the default behavior in Node. In the meanwhile I specced and Petka added (with support from others) a hook for finding these errors:

process.on("unhandledRejection", (err, p) => {
    console.error(err); // print the error
});

Note that this might catch some false negatives if you're performing .catch asynchronously itself - in my experience that's very rare.

Also note that with promises your server typically isn't in an unknown state and you can and should attempt to recover from errors when it makes sense. Since promises all the way means throw-safe code you can have fine grained error handling.

Note that promises make the async library largely unneeded. If you still wish to use callbacks and just wish "those pesky promises" would leave you alone and let you keep writing callbacks, that's fine - promises are throw safe but you can escape that by executing things off the promise code:

myPromiseFn().then(v => {
    process.nextTick(() => cb(null, v)); // next tick, to escape the chain
}, e => process.nextTick(() => cb(e));

Note that fair promise libraries also come with a asCallback callback for converting the promise code to a node err-back callback.

(1) Some people claim there is no problem, go figure


Thanks to Ben's answer I discovered it's possible to convert a promise to a callback using a module such as nodeify. This allows us to keep all our code using callbacks, and avoids errors getting swallowed by the promise. Very useful.


Need Your Help

MySQL hanging when using UPDATE CASE WHEN for saving reordering list

mysql sql

I'm using MySQL UPDATE CASE WHEN ELSE statement to update an ordered list on my web application. I have a html table with the sortable drag-and-drop plugin, and on the stop event I hit a servlet that

return indices from filtered, sorted array with numpy

python arrays sorting numpy indexing

What is the most straightforward way to do the following in python/numpy?