javascript - 我如何处理错误然后立即脱离 promise 链?

标签 javascript node.js express promise

所以我有一个 Express 应用程序,它使用中间件来解析 JSON POST 请求,然后填充一个 req.body 对象。然后我有一个 promise 链,它使用 Joi 根据模式验证数据,然后将其存储在数据库中。

我想做的是检查在这些过程之一之后是否抛出错误,通过发送状态代码适本地处理它,然后完全中止 promise 链。我觉得应该有一些非常干净和简单的方法来做到这一点,(也许是某种中断声明?)但我无法在任何地方找到它。这是我的代码。我留下了我希望中止 promise 链的地方的评论。

const joi = require("joi");

const createUserSchema = joi.object().keys({
    username: joi.string().alphanum().min(4).max(30).required(),
    password: joi.string().alphanum().min(2).max(30).required(),
});

//Here begins my promise chain 
app.post("/createUser", (req, res) => {
    //validate javascript object against the createUserSchema before storing in database
    createUserSchema.validate(req.body)
        .catch(validationError => {
           res.sendStatus(400);

           //CLEANLY ABORT the promise chain here

           })
        .then(validatedUser => {
            //accepts a hash of inputs and stores it in a database 
            return createUser({
                    username: validatedUser.username,
                    password: validatedUser.password
                })
        .catch(error => {
            res.sendStatus(500);

            //CLEANLY ABORT the promise chain here

        })
        //Only now, if both promises are resolved do I send status 200
        .then(() => {
            res.sendStatus(200); 
            }                 
        )

});

最佳答案

您不能在中间中止 promise 链。它将在链的后面调用 .then().catch()(假设两者都存在,并假设您的 promise 解决或拒绝)。

通常,您处理此问题的方式是将一个 .catch() 放在链的末尾,它会检查错误类型并采取适当的措施。您不处理链中较早的错误。你让最后的 .catch() 处理事情。

我的建议是:

// helper function
function err(status, msg) {
    let obj = new Error(msg);
    obj.status = status;
    return obj;
}

//Here begins my promise chain 
app.post("/createUser", (req, res) => {
    //validate javascript object against the createUserSchema before storing in database
    createUserSchema.validate(req.body).catch(validationError => {
        throw err("validateError", 400)
    }).then(validatedUser => {
            //accepts a hash of inputs and stores it in a database 
            return createUser({
                    username: validatedUser.username,
                    password: validatedUser.password
            }).catch(err => {
                throw err("createUserError", 500);
            });
    }).then(() => {
        // success
        res.sendStatus(200); 
    }).catch(error => {
        console.log(error);
        if (error && error.status) {
            res.sendStatus(error.status);
        } else {
            // no specific error status specified
            res.sendStatus(500);
        }
    });
});

这有几个优点:

  1. 任何错误都会传播到记录链末端的最后一个 .catch(),并在代码中的一个位置发送适当的状态。
  2. 成功仅在发送该状态的一个地方处理。
  3. 这可以无限扩展到链中的更多链接。如果您有更多可能出错的操作,它们可以“中止”链的其余部分(最后一个 .catch() 除外,只需使用适当的错误对象拒绝)。
  4. 这有点类似于没有在整个函数中使用大量return value 语句的设计实践,而是累积结果然后在最后返回它,有些人认为这是一个很好的实践对于一个复杂的函数。
  5. 调试时,您可以在一个 .then() 和一个 .catch() 中设置断点,以查看 promise 链的最终解析,因为整个链都经过最后一个 .then() 或最后一个 .catch()

关于javascript - 我如何处理错误然后立即脱离 promise 链?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51941655/

相关文章:

java - 如何在android java代码中将字符串存储到文件中并在javascript中调用它进行解析

javascript - 粘性js脚本问题

javascript - QML context2d 线宽

javascript - 在 node.js 中使用异步 waterfall 时的 "err"参数

javascript - express-typescript 项目的文件夹结构

node.js - 如何将参数传递给express.js中的嵌套 Controller ?

node.js - 使用 Nodemailer,如何使用别名 gmail 帐户发送电子邮件?或一组谷歌套件服务器帐户?

javascript - 删除添加空值的Javascript对象项

javascript - 使用 Sequelize 按相关关键字查找所有图像,并包含要包含/排除的关键字 ID 值数组

node.js - 如何在继续执行函数之前等待循环中的所有回调