#javascript #node.js #events #promise
Вопрос:
Я учусь Node.js прямо сейчас и практикуюсь в использовании EventEmitter вместе с обещаниями.
Функция successfulOrder выполняет оба обещания: verifyStockP и verifyCardP оба обещания очень просты.
Я заметил, что когда я намеренно отклоняю одно из двух обещаний, программа работает так, как ожидалось. Код ошибки catch выполняется, как и ожидалось.
Если я принудительно выполню оба обещания, я получу следующее сообщение об ошибке: «(узел:2316) Предупреждение о необработанном отказе: карта недействительна;»
Как бы я сделал так, чтобы мы не получили эту ошибку, если и verifyStockP, и verifyCardP обещают отклонить?
Заранее благодарю вас всех!
Если у вас, ребята, есть какие-либо советы по чему-то еще, что я должен исправить в коде, я был бы очень благодарен услышать это!
const EventEmitter = require('events');
const emitter = new EventEmitter();
const successfulOrder = (prod) => {
return console.log(`Your ${prod} order has processed!`)
}
const failedOrder = (prod) => {
return console.log(`Your ${prod} order has failed to process.`)
}
emitter.on('order_successful', successfulOrder);
emitter.on('order_failed', failedOrder);
const submitOrder = (prod, prodQuantity, userCardDigits) => {
const currentStock = 10;
const verifyStockP = new Promise((resolve, reject) => {
if(prodQuantity <= currentStock) {
resolve('stock available')
}
else {
reject('out of stock')
}
})
const verifyCardP = new Promise((resolve,reject) => {
let cardDigits = 16;
if (cardDigits === userCardDigits) {
resolve('card valid')
}
else {
reject('card invalid')
}
})
verifyStockP
.then((resolvedVal) => {
console.log(resolvedVal);
return verifyCardP
}).then((resolvedVal) => {
console.log('card valid')
emitter.emit('order_successful', prod)
}).catch((error) => {
console.log(error)
// emitter.emit('order_failed', prod)
})
}
submitOrder('sunglasses', 15, 17)
Комментарии:
1. Если и verifyStockP, и verifyCardP отклоняются, то, конечно, обработка
verifyCardP
отклонения невозможна, так.then
как оно никогда не вызывается,return verifyCardP
никогда не происходит — все, что вы можете сделать, это послеverifyStockP
цепочки просто добавитьverifyCardP.catch(e=>e);
2. Или, если
verifyCardP
не полагается наverifyStockP
— использованиеPromise.all
— трудно сказать из вашего примера, так как нет абсолютно никаких причин использовать обещания для этого кода3. @JaromandaX Теперь, когда я думаю об этом, я понимаю, что ты имеешь в виду, лол… Я, по сути, использую обещания для синхронного кода! Да-а-а-а, лол, это совершенно логично!
4. Однако вы можете столкнуться с такой ситуацией в асинхронном коде — так что полезно знать, как с ней справиться
5. @JaromandaX если вы можете написать это в качестве ответа, я могу отметить правильный ответ?
Ответ №1:
Проблема в том, что если первое обещание отклоняется, второе обещание никогда не является частью цепочки обещаний, которая имеет catch
Два возможных решения …
Один из способов справиться с этим-отдельно добавить «фиктивный» улов ко второму обещанию
const p1 = new Promise((resolve, reject) => setTimeout(reject, 200, 'p1'));
const p2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'p2'));
p1
.then(r => p2)
.catch(e => console.log('error', e));
p2.catch(e => console.log('error2', e));
Вы можете увидеть результат, если первое обещание не будет отклонено здесь
const p1 = new Promise((resolve, reject) => setTimeout(resolve, 200, 'p1'));
const p2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'p2'));
p1
.then(r => p2)
.catch(e => console.log('error', e));
p2.catch(e => console.log('error2', e));
оба catch
блока выполняются
Если, однако, второе Обещание вообще не зависит от первого Обещания, и в коде так, как вы написали, это означает, что два Обещания выполняются параллельно (насколько это возможно, поскольку в вашем коде нет асинхронности) — используйте Обещание.все
const p1 = new Promise((resolve, reject) => setTimeout(reject, 100, 'p1'));
const p2 = new Promise((resolve, reject) => setTimeout(reject, 200, 'p2'));
Promise.all([p1, p2])
.then(([r1, r2]) => console.log(r1, r2))
.catch(e => console.log('error', e));