Обещание, связывающее необработанное обещание

#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));