2016-03-14 4 views
3

Я сделал много асинхронного кодирования в Node.js с обратными вызовами и отличной асинхронной библиотекой, которая отлично работает. Я пытаюсь использовать модуль, который использует обещания, но я столкнулся с проблемой, когда любые ошибки, возникшие ПОСЛЕ обещания, все еще пузырятся и пойманы обработчиком ошибок обещаний.Promise.catch является ошибкой глотания

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

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

function one (input, callback) { 

    doSomeAsyncWork(input) 
    .then(function (result) { 
    return callback(null, result); 
    }) 
    .catch(function (err) { 
    logError(err); 
    return callback(err); 
    }); 

} 

function two (err, result) { 

    if (err) { ... } 

    var x = callAMethodThatThrows(); 
    ... 

} 

one('abc', two); 

В этом примере метода callAMethodThatThrows() выдает ошибку, которая получает барботировала до обещания улова() блока. Это предотвращает сбой приложения и оставляет его в неизвестном состоянии.

Любой совет будет очень благодарен, спасибо.

ответ

3

Да, извините за это - мы исправляем (1) поведение по умолчанию в узле. В то же время я specced и Petka добавил (при поддержке со стороны других) крюк для нахождения этих ошибок:

process.on("unhandledRejection", (err, p) => { 
    console.error(err); // print the error 
}); 

Обратите внимание, что это может поймать некоторые ложные негативы, если вы выполняете .catch асинхронно сам - по моему опыту, это очень редко.

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

Обратите внимание, что обещания делают асинхронную библиотеку в значительной степени ненужной. Если вы все еще хотите использовать обратные вызовы и просто хотите, чтобы «эти надоедливые обещания» оставили бы вас в покое и позволили бы вам писать обратные вызовы, все в порядке - обещания безопасны, но вы можете избежать этого, выполняя вещи off Код соглашения:

myPromiseFn().then(v => { 
    process.nextTick(() => cb(null, v)); // next tick, to escape the chain 
}, e => process.nextTick(() => cb(e)); 

Обратите внимание, что библиотеки с честным обещанием также поставляются с обратным вызовом asCallback для преобразования кода обещания в обратный вызов обратного вызова узла.

(1) Некоторые люди утверждают, что нет никаких проблем, идти рисунок

+0

Спасибо, Бен, это помогло. В настоящее время наша база кода написана с использованием обратных вызовов, поэтому для нас имеет смысл придерживаться одного способа делать что-то. Я с нетерпением жду ключевых слов async/wait, чтобы приземлиться, поэтому нам не нужно беспокоиться об этих вещах! –

+1

@ JoshCole async/await - это просто сахар для обещаний. Ваш ответ (с помощью nodeify) в порядке - лично я бы сделал это с bluebird и 'asCallback', но оба они в порядке. В общем, для библиотеки не рекомендуется предлагать API обещаний без какого-либо способа отказаться от него. –

+0

Полезно знать.Тем не менее, если мы собираемся потратить время на рефакторинг нашего кода, я предпочел бы подождать, пока у нас не будет сахара. Приветствия. –

1

Благодаря ответу Бена я обнаружил, что можно преобразовать обещание обратного вызова с помощью модуля, таких как nodeify. Это позволяет нам сохранять весь наш код с помощью обратных вызовов и избегать ошибок, проглатываемых обещанием. Очень полезно.

Смежные вопросы