Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to show exceptions on unhandled errors in Q promises

Tags:

q

I have noticed that if a .then() callback fails due to whatever error (e.g. operation on undefined variable) and there is no .catch() associated, the error is silently ignored.

This is quite uncomfortable during development.

For example, this code will exit without showing any error:

var Q = require('q');

var promise = Q('something');
promise
.then(function() {
  buggyCode();
})

A possible fix would be to manually add an error handler like this, but isn't there anything built-in for that?

.catch(function(error) {
  console.error(error.stack);
})
like image 286
Alicia Avatar asked Sep 30 '22 05:09

Alicia


2 Answers

Apparently this is a limitation of Q.

In order to make error handling slightly more verbose, there is the method .done(), which should be called after all other handlers and performs error reporting, similarly to the snippet I posted in my question.

This is less than perfect because it requires every promise-consumer function to call .done() in order for this check to work.

like image 112
Alicia Avatar answered Dec 22 '22 21:12

Alicia


This isn't necessarily a limitation of Q.

Your original example uses a then() without a catch(), which is kinda an anti-pattern with Q. then() is intended to consume any rejections, or thrown errors, returning a rejected promise itself; this is why you have to "catch()" the rejected promise, or it disappears into the void:

someFn()
  .then(doStuff)
  .catch(handleError)

If your goal is to allow the exception to be thrown, done() is intended for this purpose, as it will bubble up any error thrown within its handler, allowing a more traditional error handling approach:

try {
    someFnThatGeneratesAnError().done()
} catch(e) { ... }

As you mentioned, a done() is required after the catch() to surface any exception the error handler may have thrown, but Q has a global onerror property that allows you to provide a handler for the case when a done() isn't handled, so you can omit this from individual calls, and catch them all globally if you prefer.

Here is an example that shows error handling using both catch() and onerror, also showing how then() handles errors vs done().

like image 30
Mike MacMillan Avatar answered Dec 22 '22 20:12

Mike MacMillan