简体   繁体   中英

Why catch at the end of promise chain is not catching all the errors?

i have simple validation promises in my code which i execute like so

inBlacklist(address)
    .then(isUsed(payments))
    .then(isProcessed(ref_num))
    .then(validateType(type))
    .catch((err) => {
        console.log(err);
        return res.status(400).send({ message: err.message });
    });

Which basically checks if the payment is propertly processed or not.

Here are the promises


export const isUsed = (payments) =>
    new Promise((resolve, reject) => {
        if (payments) {
            const paymentsData = payments.map((i) => {
                i.date = moment(i.date).startOf('minute').format('YYYY-MM-DD HH:mm');
                i.amount = parseInt(i.amount);
                return i;
            });

            Transaction.findOne(paymentsData)
                .exec()
                .then((data) => {
                    if (data.length) {
                        reject({ message: 'Payment is already used', status: 409 });
                    } else {
                        resolve(false);
                    }
                })
                .catch((err) => {
                    reject(err);
                });
        }
    });

export const inBlacklist = (address) =>
    new Promise((resolve, reject) => {
        Blacklist.exists({ blocked: true, address })
            .then((blocked) => {
                
                if (blocked) {
                    return reject({ message: 'Address is in blacklist', status: 406 });
                } else {
                    return resolve(false);
                }
            })
            .catch((err) => {
                return reject(err);
            });
    });

export const isProcessed = (ref_num) =>
    new Promise((resolve, reject) => {
        if (ref_num) {
            Transaction.exists({ ref_num, status: { $in: ['processing', 'expired', 'resolved'] } })
                .exec()
                .then((data) => {
                    return reject({ message: 'Payment is already used', status: 422 });
                })
                .catch((err) => {
                    reject(err);
                });
        } else {
            return resolve(false);
        }
    });

export const validateType = (type) =>
    new Promise((resolve, reject) => {
        const validTypes = ['bitcoin', 'dash'];

        if (validTypes.includes(type)) {
            return resolve();
        } else {
            return reject({ message: 'Invalid crypto type', status: 422 });
        }
    });

Now when i call the chain, it only works in case when inBlacklist was rejected. For the others it appears as an unhandled error, which just shows up on console and doesnt return the response for api.

I have also tried this

Promise.all([inBlacklist(address), isUsed(payments), isProcessed(ref_num), validateType(type)]).catch((err) => {
    return res.status(err.status || 400).send({ message: err.message });
});

Which works fine, but what if i want to use the first variant? Why i cant catch all the promise rejections in one.catch block?

Looks like the issue is that isUsed is being executed immediately rather than after inBlacklist resolves, so your .then() is being given a Promise object rather than a callback function. It's just like if you wrote a(b(c)); , b is executed first and then the return value is passed to a .

Instead, you want to pass to .then a callback function that executes the next function, so try using arrow functions inside the then s, like so:

inBlacklist(address)
    .then(() => isUsed(payments))
    .then(() => isProcessed(ref_num))
    .then(() => validateType(type))
    .catch((err) => {
        console.log(err);
        return res.status(400).send({ message: err.message });
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM