Как я могу работать с обработчиком ошибок Bluebird?
Введение
Этот вопрос направлен, в конечном счете, на решение проблемы, которую я испытываю при разработке с Bluebird. Тем не менее, я также использую возможность получить некоторые разъяснения, так что будут побочные вопросы. Я также заранее извиняюсь за любые чувства замешательства или скуки, которые могут возникнуть при чтении истории.
Вопросы
Насколько я понимаю, Bluebird пытается разумно поймать игнорируемые отклонения в соответствии со следующей стратегией:
Второй подход, который по умолчанию берет синийbird, заключается в вызове зарегистрированного обработчика, если отклонение не обрабатывается началом второго поворота. - Обработка ошибок Bluebird Readme #
Теперь в этом заключается первый вопрос: Что означает "начало второго поворота"?
Далее в том же разделе документируется следующее:
Конечно, это не идеально, если ваш код по какой-то причине нуждается в том, чтобы напасть и приложить обработчик ошибок к некоторым обещаниям после того, как обещание уже давно висит, тогда вы увидите раздражающие сообщения. В этом случае вы можете использовать метод .done(), чтобы сигнализировать о том, что должны быть выбраны любые зависающие исключения. - Обработка ошибок Bluebird Readme #
Теперь я считаю, что столкнулся с ситуацией, описанной выше, в моем случае использования:
-
Я вызываю функцию, которая предоставит мне обещание, к которому я прикрепляю .catch()
:
lib.loadUrls()
.catch(function(e){console.log(e);});
-
Внутри эта функция загружает контент из URL1 и на основе содержимого, последовательно загружает контент из URL2:
lib.loadUrls =
return this.loadUrl1()
.then(this.loadUrl2.bind(this))
-
Если второе обещание в этой цепочке отвергнуто, ошибка обрабатывается сначала уловом, а затем обработчиком Bluebirds Possibly unhandled error
.
Последнее поведение нежелательно, и я не могу понять, почему он это делает. Таким образом, вопрос второй может быть: Почему, несмотря на то, что обработчик ошибок подключен и выполнен, Bluebird все еще рассматривает возможность "необработанной" ошибки?
Я думаю, очевидно, что обещание "какое-то время висит", когда отказ отклоняется к .catch()
. В этом случае я должен решить эту проблему (согласно цитированной документации) с помощью ".done()
".
Теперь я пробовал несколько вещей, но я не могу понять, как "использовать .done" в этом сценарии. (Это не помогает, что .done()
возвращает undefined, предотвращая меня от .finally
-ing.)
Итак, это вводит мои третий и четвертый вопросы: Как использовать .done()
в этом сценарии и , как явным образом заключу цепочку обещаний, но при этом присоединяю a .finally()
EDIT 1: Я создал несколько JSFiddles для воспроизведения ошибки:
РЕДАКТИРОВАТЬ 2: Dev исправил ошибку.
Ответы
Ответ 1
Это действительно просто ошибка регрессии в синей птице и теперь исправлена.
Немного о необходимости использования .done()
довольно теоретически, вы не будете работать в ситуации на практике, где вам нужно будет подключать обработчики ошибок таким образом, чтобы можно было сообщить о ложных срабатываниях.
Ответ 2
Скорее всего, ошибка Bluebird, поскольку обработанная ошибка не должна сообщаться (предполагая, что вы правильно обрабатываете promises в теле loadUrls
). Поэтому, вероятно, вы должны сообщить об этом отслеживателю проблем Bluebird.
Относительно done
, это функция чистого доступа, которая лучше всего используется, если используется вместо then
или catch
, когда вы просто обрабатываете разрешенное значение.
Хорошо рассматривать done
как функцию первого выбора и использовать then
и catch
только в том случае, если вам действительно нужно преобразование в другое обещание. При таком подходе вам также не нужно полагаться на мониторинг ошибок ошибок (лучше всего полностью отключить его).
В вашем случае done
следует использовать как:
lib.loadUrls().done(); // eventual error will be thrown
и если по какой-либо причине вы хотите обработать ошибку (например, на запущенном сервере, который вы не хотите его выбросить), выполните следующие действия:
lib.loadUrls().done(null, function (error) {
// handle error
});
EDIT:
Только что заметил, что вы все еще хотите обработать обещание, возвращенное lib.loadUrls().catch(..)
с помощью finally
. В таком случае done
не является решением. done
следует использовать только как окончательный вызов, но вы можете объединить его с finally
следующим образом:
lib.loadUrls().finally(function () {
// cleanup
}).done();