如何在出现异常后继续进行异步查找?

问题描述 投票:0回答:1

在我的 Node.js 我有一个叫做 employees 其中存储了电子邮件的列表。我解析了该列表,并尝试通过以下方式为每个人分别发送邮件。颔联 包。此外,我还使用 对于异步 包。

在循环的某次迭代中可能会出现错误。即使发生错误,我也想继续循环。似乎我不能使用 continue 陈述我的情况 你有什么解决方案推荐?

const forAsync = require('for-async');

forAsync(employees, (employee) => {
    return new Promise(resolve => {
        // Set options.
        const options = {
            from: process.env.EMAIL,
            to: employee,
            subject: "System notification",
            html: html
        };

        // Send mail with defined transport object.
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                transporter.sendMail(options, (error) => {
                    if(error) {
                        console.log(error);
                        reject(error);
                    } else {
                        resolve();
                    }
                });
            }, 1000);
        }).then(() => {
            resolve();
        }).catch(error => {
            console.log(error);
        );
    });
});

EDIT:

router.post('/notifications', function(request, response) {
    // Make sql requests to the database.

    Promise.all([firstQuery, secondQuery, thirdQuery]).then(responses => {
        // Some logic

        await Promise.all(employees.map(async (employee) => { // <- PROBLEM
            try {
                await sendEmail(transporter, options);
            } catch (error) {
                // Error sending this specific email, just report it and ignore
                console.log(error);
            }
        }));
    });
});
javascript asynchronous
1个回答
2
投票

由于你使用的是相当新的Node.js版本,我会使用一个 async 的函数和一个 for 循环。

首先,由于 transporter.sendEmail 是一个老式的回调式函数,我会在某个utilities模块中为它创建一个封装器。

function sendEmail(transporter, options) {
    return new Promise((resolve, reject) => {
        transporter.sendMail(options, (error) => {
            if (error) {
                reject(error);
            } else {
                resolve();
            }
        });
    });
}

然后循环(在一个 async 函数)将是。

for (const employee of employees) {
    try {
        await sendEmail(transporter, {
            from: process.env.EMAIL,
            to: employee,
            subject: "System notification",
            html: html
        });
    } catch (error) {
        // Error sending this specific email, just report it and ignore
        console.log(error);
    }
}

The trycatch 防止任何错误或承诺拒绝传播出循环,因此循环继续。注意,邮件将以 系列,不在 平行.

我去掉了一秒的延迟,因为我认为你并不真正需要它,但如果你想要它,可以添加一个新的延迟。delay 函数到你的实用程序中。

function delay(ms, value) {
    return new Promise(resolve => setTimeout(resolve, ms, value));
}

然后把这个插入到 for 循环。

await delay(1000);

如果你想用并行的方式而不是串联的方式来完成这个任务,你就会想... Promise.all 以及各个承诺的拒绝处理程序。

await Promise.all(employees.map(async (employee) => {
    try {
        await sendEmail(transporter, {
            from: process.env.EMAIL,
            to: employee,
            subject: "System notification",
            html: html
        });
    } catch (error) {
        // Error sending this specific email, just report it and ignore
        console.log(error);
    }
}));

await Promise.all(employees.map(employee => sendEmail(transporter, {
        from: process.env.EMAIL,
        to: employee,
        subject: "System notification",
        html: html
    }).catch(error) {
        // Error sending this specific email, just report it and ignore
        console.log(error);
    })
);
© www.soinside.com 2019 - 2024. All rights reserved.