Как мне отладить мой асинхронный код, основанный на промисах, если библиотека поглощает все исключения?

Проблема

JSFiddle: http://jsfiddle.net/missingno/Gz8Pe/2/

У меня есть код, который выглядит так:

var d = new Deferred();
d.resolve(17);
return d.then(function(){
     //do some stuff...
})
.then(function(){
    var obj = a_funtion_that_returns_null_on_IE();
    var x = obj.some_property; //BOOM!
});

Проблема в том, что когда я работаю в IE, все, что я вижу, это 'obj' is null or not an object ошибки, без какой-либо ссылки на соответствующий номер строки и без остановки отладчика на проблемной строке (как мне бы этого хотелось).

Подобные проблемы затрудняют отладку кода, и единственные решения, которые я могу придумать прямо сейчас (возиться с библиотекой потока управления или прибегать к пошаговой отладке с помощью отладчика или console.log), — это то, что я лучше бы не пришлось.

Что я думаю, происходит

Чтобы разрешить добавление errbacks после запуска цепочки, then будет упреждающе перехватывать любые исключения, вызванные обратными вызовами. Я думаю, что это причина того, что отладчик IE не останавливается на ошибке или не показывает обычное сообщение об ошибке с номером строки в нем.

Сообщения об ошибках без номеров строк поступают из библиотеки управления потоком: она предоставляет хук deferredOnError, который вызывается всякий раз, когда исключение перехватывается и сохраняется на потом, а поведение по умолчанию — console.error-ing объект Error:

dojo.config.deferredOnError = function(err){
    //a chance to log the exception after it is captured by "then"
    //or do other things with it
    console.error(err);
}

К сожалению, я не смог найти способ получить номер строки или трассировку стека из объекта ошибки в IE, а хук вызывается таким образом, что я не могу просто повторно сгенерировать исключение и позволить ему подняться на верхний уровень.

Что я хочу

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


person hugomg    schedule 07.02.2012    source источник
comment
Вы пробовали использовать Firebug Lite? Это может быть болезненно медленным, но это также может быть меньше, чем инструменты разработчика IE.   -  person Matt Ball    schedule 08.02.2012
comment
@MДΓΓБДLL: я думал, что firebug-lite был для console.log и тому подобного ... В остальном мне очень удобно работать с инструментами разработчика IE9 (то есть, когда я вынужден их использовать ...)   -  person hugomg    schedule 08.02.2012
comment
На самом деле это не ответ, но я бы предложил использовать библиотеку Promise, которая не проглатывает исключения. К сожалению, это моя самая большая претензия к большинству реализаций Promises/A, все они кажутся делать это. Есть отложенные, которые этого не делают, а именно jQuery. Тот, кто написал эту спецификацию, очевидно, не подумал о последствиях отладки. Если обратный вызов выдает ошибку, возвращенное обещание будет переведено в состояние сбоя.   -  person gnarf    schedule 27.04.2012
comment
@gnarf: На самом деле это было именно то, что я сделал через некоторое время. В любом случае, я просто записал ответ, чтобы решить эту дилемму :)   -  person hugomg    schedule 27.04.2012


Ответы (3)


Это работает с любой структурой без предварительной настройки, и все последние браузеры поддерживают это.

Приостанавливать обнаруженные исключения: Это фактически остановит выполнение javascript и приведет вас именно туда, где находится проблемный код, как это происходит.

Пауза при перехваченных исключениях

В Хроме:

  1. Инструменты разработчика,
  2. вкладку Источники,
  3. Пауза в исключениях (значок остановки), а затем
  4. флажок Пауза при перехваченных исключениях
person fregante    schedule 11.11.2014
comment
Хорошая точка зрения! Интересно, было ли это доступно еще в 2012 году? - person hugomg; 12.11.2014
comment
эээ, это уже не имеет значения, хорошо, что оно у нас есть. :) Когда я понял, что эта функция поможет мне с отладкой промисов, я был счастлив. - person fregante; 12.11.2014
comment
У вас то же самое в Firefox, см. developer.mozilla.org/ en-US/docs/Tools/Debugger/How_to/ - person Bertrand P; 23.06.2020

Что я в итоге сделал

Я добавил функцию секвенирования в свою мини-библиотеку асинхронных вспомогательных функций. По сути, он запускает последовательность вызовов «затем», за исключением того, что он добавляет дополнительные промежуточные шаги для повторного создания любых исключений, которые в конечном итоге перехватываются отложенными вызовами. Он также принимает необязательный обработчик ошибок для перехвата исключений.

Когда я вызываю его, это выглядит так:

go([
    function(){
        return 17;
    },
    function(x){
        //return some stuff
    },
    function(){
         var obj = a_function_that_returns_null_on_IE();
         var x = obj.some_property; //BOOM!
    }
], function(){
    //an optional error handler
});

Еще одна причина, по которой я поступил таким образом, заключается в том, что у меня есть много кода, который должен работать одновременно с синхронным или асинхронным кодом (используя Deferred.when для создания цепочки). Использование моей пользовательской функции позволило мне использовать единый унифицированный синтаксис, а ошибки, которые не фиксируются в асинхронном случае, согласуются с синхронным случаем, в котором не задействованы отложенные. Я также думаю, что можно не фиксировать ошибку, поскольку, в отличие от общего случая, когда я использую «go», я заранее знаю, какой код будет вызываться, поэтому нет необходимости фиксировать исключения, если кому-то нужно поймать их в будущем.

Кроме того, использование пользовательского решения дало мне свободу применять некоторые личные предпочтения в дизайне :)


Вдобавок к этому я уменьшил количество исключений, которые я генерирую сам во всей кодовой базе. Управление исключениями в асинхронном коде более раздражает, чем обычно, и иногда проще просто вернуться к обработке условий ошибки, возвращая null или код ошибки.

Кроме того, мы убедились, что любые исключения, которые мы создаем сами, являются экземплярами встроенного класса Error, а не другими объектами. Причина в том, что встроенный класс Error записывает номер строки и трассировку стека, где он был сгенерирован, своего рода кросс-браузерным способом.

person hugomg    schedule 27.04.2012

Решение 2016 года

Если вы используете нативные обещания ES, ничего не делайте; Chrome автоматически сообщает о неперехваченных отклонениях обещаний в консоли.

Ошибка Uncaught Promise в инструментах разработчика Chrome

Обратите внимание, что перехваченный (Second fail) ничего не показывает, но неперехваченный отказ появляется в консоли после завершения выполнения кода.

person fregante    schedule 04.03.2016