Возникло явное лишнее событие unhandledRejection - PullRequest
0 голосов
/ 23 декабря 2018

Мы добавили обработчик события для "unhandledRejection" в нашем приложении узла, этот обработчик завершает процесс (как говорит узел, по умолчанию скоро ).

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

Мы используем Q.allSettled (который обрабатывает отклоненные обещания), я вижу в отладчике, что массив обещаний имеет два элемента: первый отклоненный ивторой в ожидании (будет разрешен ).После установки точек останова в обработчике unhandledRejection и в then после allSettled я сначала получаю unhandledRejection, а сразу после then (так, обработано отклонение ).

Документация для unhandledRejection гласит (выделено мое):

Событие 'unhandledRejection' генерируется всякий раз, когда Promise отклоняется и обработчик ошибок не присоединяется к обещанию в пределах цикла событий.

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

Лучший минимальный пример, который мне удалось придумать, немного надуманный, но я думаю, что у него та же основная причина, что и у нашего кода.Я что-то здесь упускаю?Как узел может заставить unhandledRejection завершить процесс по умолчанию, если это возможно?

process.on("unhandledRejection", (reason, p) => {
    console.error(`### Got unhandled rejection: '${reason}'`);
});


function doesNotFireUnhandledRejection() {
    let rejected = Promise.reject('an error');
    return new Promise((resolve, reject) => {
        resolve(rejected);
    })
    .catch(err => console.log("Caught:", err));
}


function firesUnhandledRejection() {
    let rejected = Promise.reject('an error');
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(rejected), 0);
    })
    .catch(err => console.log("Caught:", err));
}

Кстати, то же самое происходит с setImmediate, но не с process.nextTick (хотя я мог поклясться, что на прошлой неделеprocess.nextTick сделал причиной события ...).

Ответы [ 2 ]

0 голосов
/ 23 декабря 2018

Чтобы ответить на ваш вопрос:

  • Вещи, имеющие семантику микрозадач (обработчики process.nextTick, then, продолжения асинхронных функций и enqueueMicrotask), происходят до необработанной проверки отклонения.
  • Вещи, имеющие семантику макрозадач (таймеры, ввод / вывод), происходят после необработанной проверки отклонения.

Это то, что мы подразумеваем под: «в поворотецикла событий ".

Node.js ведет себя как положено в этом случае.Обратите внимание, что в вашем случае:

function firesUnhandledRejection() {
    let rejected = Promise.reject('an error'); // < -- this is the unhandled rejection
    return new Promise((resolve, reject) => { // <- this promise is totally fine
        setTimeout(() => resolve(rejected), 0); // <- you associate them too late
    })
    .catch(err => console.log("Caught:", err));
}

Итак, проблема в том, что слишком долго (срабатывание таймеров) существует отклоненное обещание без обработчика ошибок.

0 голосов
/ 23 декабря 2018

Вот как процесс может быть остановлен при необработанном отклонении (ожидается, что поведение узла будет использоваться по умолчанию в будущих версиях):

process.on('unhandledRejection', err => {
  console.error(err);
  process.exit(1);
});

Отклоненное обещание должно быть приковано с catch(...) или then(..., ...) на том же тикев противном случае это считается необработанным отклонением.

В редких случаях, когда гарантируется, что отклонение будет обработано позднее, обещание можно приковать фиктивной catch для подавления обнаружения необработанного отклонения:

function firesUnhandledRejection() {
    const rejectedPromise = Promise.reject('an error');
    rejectedPromise.catch(() => {});

    return new Promise((resolve) => {
        setTimeout(() => resolve(rejectedPromise), 0);
    })
    .catch(err => console.log("Caught:", err));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...