Как я могу работать с обработчиком ошибок 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();