【问题标题】:What is the correct way to handle promise rejections with async/await in node.js?在 node.js 中使用 async/await 处理承诺拒绝的正确方法是什么?
【发布时间】:2018-06-10 18:27:30
【问题描述】:

我在 node.js v8.9 中有以下处理用户注册的函数:

module.exports = async (req,res) =>{
    const User = req.app.locals.User;
    const user =User.build({
        email: req.body.email,
        displayName: req.body.display_name,
        realName: req.body.real_name,
        hashedPassword:req.body.password ,
        role: 0   
    });

    try{
        await user.save();
        res.send({message:"Usuario creado exitosamente.", success:true });
    }
    catch(ex)
    {
        res.send({message:"Información es inválida:", success:false});
    }

    res.end();
};

如您所见,当用户未成功创建时,我正在使用 async 和 await 进行处理。但是,当创建失败时,我的 catch() 永远不会执行。为什么?有没有不同的方法来处理异步/等待的承诺拒绝?有人建议使用 thow new Error(),但我不想抛出错误,我只想向客户端发送一条消息。

更多背景信息:该应用使用 Express.js 制作,并使用 Sequelize.js 作为 ORM。我已将我的用户模型保存到 req.app.locals 中,以便我可以从我的路由处理程序访问它。实际保存到 MS SQL Server 中的数据表对 email 列有一个 UNIQUE 约束,对于使用现有电子邮件注册的用户将导致 user.save() 承诺失败。

测试时,在控制台中,我看到 sequelize.js 的异常说 UNIQUE 约束不允许创建记录。但是,我的 catch 语句没有被执行,客户端(在本例中为浏览器)一直等待响应,直到超时。如果我将 async/await 更改为使用 .then().catch() 它可以正常工作(也不需要 try/catch 块)。

【问题讨论】:

  • 可能您的 User.save() 没有正确拒绝承诺。
  • “创建失败”是什么意思? User.build 会抛出异常还是什么?
  • 由于缺少minimal reproducible example 的问题,我投票结束,但您的标题问题将与Correct Try…Catch Syntax Using Async/Await 重复
  • @tutiplain 听起来你会想要 await build 调用然后将其放在 try 块中而不是它之前。
  • @Bergi - 根据this doc 看起来User.build() 返回一个模型并且不是异步的。而且,user.save() 似乎是异步的并且确实返回了一个承诺。除非User 不是OP 认为的那样,并且在try 块之前引发异常,否则不确定错误在哪里。

标签: node.js promise async-await


【解决方案1】:

我看到了几个问题(这显然是导致您的问题的原因):

  1. res.send() 的两个实例更改为res.json()
  2. 删除res.end()

如果您想发送一个对象作为响应,那么您需要发送 JSON。您可以使用 res.send(JSON.stringify(obj)) 或 Express 有 res.json(obj) 为您转换对象。

而且,res.end() 只需要 res.write()res.send()res.json() 都已经包含 res.end()

【讨论】:

  • 这行得通,但我不明白为什么。我使用 res.end() 有什么不同?
  • @tutiplain - 您的问题从未非常具体地说明发生了什么错误以及代码中发生的位置。如果您想调试旧代码,那么您应该使用console.log() 语句对其进行检测,以遵循代码流并查看到底发生了什么。我们不能为你这样做。在res.send()res.json() 之后调用res.end() 是一个错误,因为res.send()res.json() 已经在内部调用了res.end()。我不知道当您在同一响应中两次调用 res.end() 时会发生什么,但这是不正确的。
  • @tutiplain - res.json() 需要发送正确的 JSON 响应。尝试执行res.send(obj) 最终会发送一个字符串[object Object],这可能不是您的收件人所期望的。
【解决方案2】:

尝试/捕捉。因为 await 中的 Promise 拒绝会引发异常。

【讨论】:

    【解决方案3】:

    正确的方法是像这样将返回值影响到变量:

    try{
            [err,resp] = await user.save();
            res.send({message:"Usuario creado exitosamente.", success:true });
    }
    

    然后您可以检查是否有错误,例如

    【讨论】:

    • 我发现这种方法很有趣,但我无法让它发挥作用。
    猜你喜欢
    • 2018-12-16
    • 2018-09-14
    • 2018-09-28
    • 1970-01-01
    • 2020-02-08
    • 2017-06-04
    • 2017-12-10
    • 2018-01-18
    相关资源
    最近更新 更多