64

I would like to catch all unhandled exceptions/rejections that take place within a javascript Promise. Is there a good method for catching them without adding a .catch(..) on each end of the Promise chain? (in case of forgetting to add this, the error silently disappears).

The developer console in Google Chrome can log them, I like to log them as well in a production environment.

For normal javascript exceptions I use the window.onerror function, but the errors from a Promise call this function.

Example:

window.onerror = function (e) {
    alert("unhandled error: " + e);
};

var p = new Promise(function (resolve, reject) {
    var nullObject = null;
    // Raise a TypeError: Cannot read property 'forceNullError' of null
    var x = nullObject.forceNullError(); 
    resolve();
});

p.then(function () { alert('success'); });

JSFiddle: https://jsfiddle.net/f7zwej6L/

*) I noticed that WinJS has a .done(..) method for what I want, but Native Promises don't.

Peter Mols
  • 1,011
  • 1
  • 9
  • 13
  • `.done` is equivalent to `.then(done, done);` where `done` is some function - so no great loss there – Jaromanda X Jul 17 '15 at 09:24
  • @JaromandaX thank you for your response. I found this on MSDN "Unhandled exceptions in a then function are silently captured as part of the state of the promise, but unhandled exceptions in a done function are thrown." [msdn](https://msdn.microsoft.com/en-us/library/windows/apps/hh700337.aspx). – Peter Mols Jul 17 '15 at 09:42
  • No, `.done` is **not** equivalent to `.then(done, done)`. See http://stackoverflow.com/questions/26667598/will-javascript-es6-promise-support-done-api/26667655#26667655. –  Jul 17 '15 at 11:43

4 Answers4

98

The whole world is waiting for the unhandledrejection and rejectionhandled events. As of March 2016, Chrome is now the first to support it.

Example:

window.addEventListener('unhandledrejection', function(event) {
    console.error('Unhandled rejection (promise: ', event.promise, ', reason: ', event.reason, ').');
});

Specification: HTML Living Standard

Mozilla Developer: onrejectionhandled, onunhandledrejection

Chromium Issues: 495801, 393913

Richard Connamacher
  • 3,115
  • 19
  • 21
Valentin Shergin
  • 7,166
  • 2
  • 50
  • 53
  • Seems that it is already in Chromium's trunk and that Firefox really wants implement it too. I think it will be available very soon. – Valentin Shergin Oct 05 '15 at 17:26
  • 1
    Edited it to correct the name of the event to "unhandledrejection", and mention that Chrome now supports it (woot!). "window.onunhandledrejection" is the property version. – Richard Connamacher Mar 22 '16 at 17:32
  • 1
    FYI for anyone using Bluebird, the `unhandledrejection` event is triggered, _but_ the promise and reason are nested underneath the `detail` key of the event (e.g. `event.detail.promise` instead of `event.promise`). See http://bluebirdjs.com/docs/api/error-management-configuration.html#global-rejection-events – Nathan Apr 30 '16 at 19:37
  • Odd. For me, it only calls these functions when "Pause on caught exceptions" is enabled. – Venryx Apr 29 '17 at 05:07
  • https://caniuse.com/#feat=unhandledrejection says supported in Chrome 49+, Chrome for Android 70+, iOS Safari 11.3+, UC Browser for Android 11.8+, Safari 11+, Opera 36+, Samsung Internet 5+, Android Browser 67+. – darrinm Dec 16 '18 at 17:05
26

Note that in Node the event is called unhandledRejection:

process.on('unhandledRejection', function(err, promise) {
    console.error('Unhandled rejection (promise: ', promise, ', reason: ', err, ').');
});

On version 12+, node will terminate on these rejections.

Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
3

Some libraries have their own APIs for doing this. Some browsers will report unhandled rejections (sooner or later).

Actually, done probably does not do what you want. This is why it is not part of the spec. In any case, you still have to remember to call it.

There is no reliable, cross-platform, cross-library way to do this.

2

uncaught library can help you to catch unhandled promise rejections.

And it handles uncaught errors as well.

EDIT

<script type="text/javascript" src=".../uncaught/lib/index.js"></script>

<script type="text/javascript">
    uncaught.start();
    uncaught.addListener(function (error) {
        console.log('Uncaught error or rejection: ', error.message);
    });
</script>

Benefit of this approach is the only one interface, which allows you to handle both uncaught errors and unhandled promise rejections.

  • 2
    But it based on the same `unhandledrejection ` event, so supported browsers are: Google Chrome 49+, Opera 41+, Yandex.Browser 16+. – Roman Bekkiev Dec 15 '16 at 12:49
  • 1
    Yes, you're right. There isn't something special in base of this approach. It only simplifies `unhandledrejection` and `error` events using. – Aleksandr Oleynikov Dec 19 '16 at 08:52