Подтвердить что ты не робот

Как поймать исключенное исключение в Promise

Есть ли способ глобально уловить все исключения, включая исключения Promise. Пример:

    window.onerror = function myErrorHandler(errorMsg, url, lineNumber) {
        alert("Error occured: " + errorMsg);//or any message
        return false;
    }

    var myClass = function(){

    }


    var pr = new Promise(function(resolve, react){
        var myInstance = new myClass();
        myInstance.undefinedFunction(); // this will throw Exception
        resolve(myInstance);
    });


    pr.then(function(result){
        console.log(result);
    });

    // i know right will be this:
    // pr.then(function(result){
    //     console.log(result);
    // }).catch(function(e){
    //     console.log(e);
    // });

Этот script будет беззвучно умирать без ошибок. Ничего в firebug.

Мой вопрос: если я ошибаюсь и забыл поймать, есть ли способ поймать его глобально?

4b9b3361

Ответ 1

Большинство реализаций обещаний в настоящее время не предоставляют тип функциональности, на которую вы ссылаетесь, но ряд сторонних библиотек обещаний (включая Q и bluebird) предоставляет метод done(), который будет захватывать и восстанавливать любые неперехваченные ошибки, выводя их на консоль.

( Изменить: см. Benjamin Gruenbaum ответ на вопрос о функциях Bluebird для обработки исключенных исключений)

Итак, если у вас есть это, вам просто нужно следовать правилу, что любое обещание, которое вы используете, должно быть возвращено или завершено с помощью .done():

pr.then(function(result){
    console.log(result);
})
.done();

Для цитаты из ссылки Q API:

Золотое правило использования done vs. then: либо return ваше обещание кому-то другому, либо если цепочка заканчивается, вызовите done, чтобы завершить его. Завершение с помощью catch недостаточно, так как обработчик catch может сам выдать ошибку.

Я понимаю, что это по-прежнему требует дополнительной работы, и вы все равно можете забыть это сделать, но это улучшение по сравнению с необходимостью .catch() и явно обрабатывать каждую ошибку, особенно по причине, указанной выше.

Ответ 2

Обновление, родной promises теперь выполняется в большинстве браузеров:

window.addEventListener("unhandledrejection", function(err, promise) { 
    // handle error here, for example log   
});

Мы просто обсуждали это на днях.

Вот как вы сделали бы это с bluebird:

window.onpossiblyunhandledexception = function(){
    window.onerror.apply(this, arguments); // call
}

window.onerror = function(err){
    console.log(err); // logs all errors
}

С Bluebird также можно использовать Promise.onPossiblyUnhandledRejection. Запросы на done не нужны, так как библиотека обнаруживает необработанное отклонение, в отличие от Q (UPDATE 2016 - теперь я написал код для Q, и он делает это).

Что касается native promises - они в конечном итоге будут сообщаться либо в window.onerror, либо в новом обработчике, но процесс спецификации еще не выполнен - ​​вы можете следовать это здесь.

Ответ 3

В Node.js вы можете использовать:

process.on('unhandledRejection', (reason, promise) => {
  console.error(`Uncaught error in`, promise);
});

Ответ 4

Если вы пишете код, который может быть выполнен как в браузере, так и в среде Node.js, вы можете обернуть свой код в функцию самоисполнения, как это:

var isNode = (typeof process !== 'undefined' && typeof process.on !== 'undefined');
(function(on, unhandledRejection) {
    // PUT ANY CODE HERE
    on(unhandledRejection, function(error, promise) {
        console.error(`Uncaught error in`, promise);
    });
    // PUT ANY CODE HERE
})(
    isNode ? process.on.bind(process) : window.addEventListener.bind(window),
    isNode ? "unhandledRejection" : "unhandledrejection"
);

Что произойдет, если вы используете этот код:

  • Если вы запустите его в среде Node.js, ваш обработчик будет привязан к объекту процесса и будет выполнен, если у вас есть неперехваченное исключение в обещании.

  • Если вы запустите его в среде браузера, ваш обработчик будет прикреплен к объекту окна и будет выполнен, когда у вас есть неперехваченное исключение в обещании, и ваш браузер поддерживает событие unhandledrejection.

  • Если вы запустите его в среде браузера без поддержки unhandledrejection, вы не сможете поймать свое неперехваченное исключение, и ваш обработчик событий unhandledrejection никогда не будет запущен, но вы не будете получить какие-либо ошибки, если нет исключенных исключений.

Ответ 5

Если вы используете родной Promise, это довольно просто.
Вам нужно только .catch отклонить некоторые из них.

ajax(request).catch(function(rejected){
      console.log(rejected);
});

Если я не поймаю его где-нибудь, обезвреженное обещание будет продолжать показывать. Но если я поймаю его где-нибудь...