Вот подмножество лотов больше кода; JavaScript в Node.js. По сути, эквивалент функции a
требует некоторого модульного тестирования (в функции b
). При возврате с b
, a
призывает к тестированию исключений (в функции c
). c
призывает к синхронному тестированию исключений (в функции d
). Позже c
вызовет другую функцию (e
, скажем) для асинхронного тестирования исключений (использование Promise reject()). Лучше всего использовать Promises везде в Node.js, но даже использование их не всегда приводит к поведению, которое я предсказываю.Почему этот JavaScript Promise reject() обрабатывается при обратном вызове результата?
'use strict';
function d() {
return new Promise(function(resolve, reject) {
console.log('start d throw test');
try {
throw new Error('Error type');
} catch (e) {
console.log('d catch block e.message=' + e.message +
' rejecting to c');
return reject(new Error('d ' + e.message));
} // catch
}) // Promise
}
function c() {
return new Promise(function(resolve, reject) {
console.log('start c');
d()
.then(// d then
function(result) { console.log('c d result callback'); },
function(error) {
console.log('c d error callback error.message=' + error.message +
' rejecting to a');
return reject(new Error('second try'));
}
) // d then
}) // Promise
}
function b() {
console.log('start b resolving to a');
return Promise.resolve();
}
function a() {
return new Promise(function(resolve, reject) {
console.log('start a');
b()
.then(// b then
function(result) {
console.log('a b result callback to c');
c();
},
function(error) {
console.log('a b error callback error.message=' + error.message);
}
) // b then
.then(// c then
function(result) {
console.log('a c result callback ');
},
function(error) {
console.log('a c error callback error.message=' + error.message);
}
) // c then
.catch(
function(error) {
console.log('a final catch error.message=' + error.message);
}
) // catch
}) // Promise
}
a();
я предсказал, например, что каждый раз, когда я выдать обещание отказаться(), обработка будет происходить в ошибке обратного вызова вызывающего абонента. (Обратите внимание, что каждый reject()
также использует new Error
.) Следовательно, я ожидал этот вывод в console.log.
start a
start b resolving to a
a b result callback to c
start c
start d throw test
d catch block e.message=Error type rejecting to c
c d error callback error.message=d Error type rejecting to a
a c error callback error.message=second try
Обратите внимание, что когда d
называется отклонять(), я предсказывал обработка будет идти на обратный вызов c
ошибки. Аналогично, c
reject() перейдет в обратный вызов ошибки a
. Вместо этого, я получаю этот выход:
start a
start b resolving to a
a b result callback to c
start c
start d throw test
d catch block e.message=Error type rejecting to c
c d error callback error.message=d Error type rejecting to a
a c result callback
c
отклонять(), похоже, идет к a
результат обратного вызова.
Функция b может быть задействована; если я напишу его из программы, я получу желаемую обработку. Это здорово для здесь, но в более крупном коде это не вариант.
Вопросы:
- Почему обработка происходит в результате обратного вызова, а не обратного вызова ошибки?
- Как функция b вызывает эффект так долго после ее завершения?
- Как я могу это исправить?
- Какие плюсы и минусы привязаны к использованию
return reject
по сравнению сreject
? Большую часть времени (по крайней мере), похоже, работает. Я не поймал более короткую форму, вызывающую проблемы.
он должен быть 'Возвращение с();' – mido
Очень интересно читать: http://pouchdb.com/2015/05/18 /we-have-a-problem-with-promises.html Вы сделали ошибку * Rookie # 5 *, вы не вернули c().Кроме того, не смешивайте вещи так много, либо используйте обратный вызов ошибки или (повторный) бросок ошибок (бросок очень рекомендуется), не оба, это запутывает. – Shanoor
@ShanShan: Спасибо, что мотивировал меня перечитать эту статью. Это одна из лучших статей о обещаниях, которые я видел. Я не полностью понял ошибку Rookie №5 раньше (очевидно). – BaldEagle