juanvicareer
juanvicareer

Reputation: 41

Promise chaining unhandled promise

I'm learning Node.js right now and practicing using EventEmitter along with promises.

The successfulOrder function runs through both promises: verifyStockP and verifyCardP both promises are super simple.

I noticed that when I purposely make one of the two promises reject, the program works as expected. The catch error code runs as expected.

If I force both promises to fail, I get the following error message: '(node:2316) UnhandledPromiseRejectionWarning: card invalid;'

How would I make it so we don't get this error if both the verifyStockP and verifyCardP promises reject?

Thank you all in advance!

If you guys have any tips on something else I should fix on the code I'd be super grateful to hear it!

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)

Upvotes: 0

Views: 148

Answers (1)

Jaromanda X
Jaromanda X

Reputation: 1

The issue is that if the first Promise rejects, the second Promise is never part of the Promise chain that has the catch

Two possible solutions ...

One way to handle this is separately add a "dummy" catch to the second promise

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

You can see the result if first promise doesn't reject here

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

both catch blocks are run

If, however, the second Promise has no reliance at all on the first Promise, and in the code the way you wrote it means that the two Promises do run in parallel (as much as they can since you have no asynchrony in your code) - use Promise.all

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

Upvotes: 1

Related Questions