【问题标题】:Promise (then - catch) or Async / Await (with Try-Catch) for exceptions controlPromise (then - catch) 或 Async / Await (with Try-Catch) 用于异常控制
【发布时间】:2020-01-02 05:14:48
【问题描述】:

我想知道如何在 async/await 中工作,如果在 async/await 中 try-catch 更方便,或者只使用 then-catch 的 Promise 而不使用 async-await

我以 Node JS 和 Express 中的这段小代码为例,以便更好地理解:

const { validationResult } = require('express-validator');
const Post = require('../models/post');

module.exports = {

    //HTTP POST Method

    createPost: async(req, res, next) => {
        const errors = validationResult(req);
        if (!errors.isEmpty()) {
            return res.status(422).json({
                errors: errors.array()[0].msg
            });
        }

        try {
            const { title, content, imageUrl } = req.body;

            const newPost = new Post({
                title,
                content,
                imageUrl
            });

            const post = await newPost.save();

            if (!post) {
                return res.status(422).json({
                    errors: 'Error'
                });
            }

            return res.status(201).json({
                message: 'Post created successfully!',
                post: {
                    title: title,
                    content: content,
                    image: imageUrl,
                }
            });

        } catch (err) {
            return res.status(500).json({
                errors: 'Error'
            });
        }
    }
}

感谢您的宝贵时间!

【问题讨论】:

  • 我不清楚你在问什么。 try/catch 将在 await 上捕获同步抛出的异常或被拒绝的承诺。你能把你的问题说得更具体一点吗?你问的是哪几行代码?
  • 仅供参考,您的if (!post) ... 声明可能永远不会被触发。如果.save() 失败,它可能会拒绝,而不是使用null 解决。来自await 的拒绝将转到您的catch()
  • @jfriend00 我想知道如何在 async/await 中工作,如果在 async/await 中 try-catch 更方便,或者只使用 Promise 而不使用 async-await,只使用 Promise然后抓住。

标签: node.js async-await try-catch


【解决方案1】:

由于您没有提出非常具体的问题,我将在您的代码中为您提供一些 cmets 和替代方案。但首先要说明几点:

使用asyncawait 进行编程是可选的。何时使用它部分取决于您的意见,部分取决于您在做什么。如果您的代码流中只有一个异步操作,那么通常没有特别的理由使用await 不那么引人注目,因为简单的.then().catch() 的复杂性与try/catch 相似.

如果您有任何需要捕获的同步抛出异常的危险,那么无论如何您都必须使用try/catch(无论您的异步设计如何)。


现在这里有一些关于您的代码的注意事项:

在这段代码中:

       const post = await newPost.save();

        if (!post) {
            return res.status(422).json({
                errors: 'Error'
            });
        }

如果newPost.save() 操作失败,那么它将拒绝承诺。如果它拒绝了承诺,那么,因为您使用的是await,该拒绝将转到您的catch() 处理程序,因此它根本不会到达if (!post) ... 块。如果该检查有用,我会感到惊讶。

由于您的控制流中只有一个异步操作,而且我没有看到任何同步抛出异常的危险,我可能会像这样使用.then().catch()

const { validationResult } = require('express-validator');
const Post = require('../models/post');

module.exports = {

    //HTTP POST Method

    createPost: (req, res, next) => {
        const errors = validationResult(req);
        if (!errors.isEmpty()) {
            return res.status(422).json({
                errors: errors.array()[0].msg
            });
        }

        const { title, content, imageUrl } = req.body;

        const newPost = new Post({
            title,
            content,
            imageUrl
        });

        newPost.save().then(post => {
            res.status(201).json({
                message: 'Post created successfully!',
                post: {
                    title: title,
                    content: content,
                    image: imageUrl,
                }
            });
        }).catch(err => {
            res.status(500).json({
                errors: 'Error'
            });
        });
    }
}

我想知道如何在 async/await 中工作,如果在 async/await 中 try-catch 更方便,或者只使用 Promise 而不使用 async-await,只使用 then 和 catch 的 Promise。

没有统一的指导方针。如果我的控制流中有一个异步操作,我使用.then().catch()。如果我有多个异步操作并且它们需要被序列化(一个接一个),那么我使用async/await。这只是我的个人风格,也是我认为最干净、最方便的风格。在其他一些情况下,async 函数仅作为默认的catch 处理程序很有用,因此任何同步抛出的异常都会自动转换为对调用者的拒绝,并且在某些情况下您可以混合使用同步和函数内部的异步流程,有时执行可能完全同步。将其包装在 async 函数中会自动确保接口始终返回一个承诺,即使在某些条件下执行是完全同步的。

这在缓存中经常出现。如果该值在缓存中,则检索它是完全同步的,但无论如何您的接口都需要返回一个 Promise。 async 函数会自动为您执行此操作。可以通过 return Promise.resolve(cachedValue) 手动编写代码,但有时 async 函数更适合这种情况。

【讨论】:

  • 非常感谢,一切都最清楚了。我的理解要好得多,我现在的问题是,如果我有一个带有异步方法(称为加密)的辅助文件(crypt.js)和两个等待(一个等待 bcrypt 盐,一个等待 bcrypt 密码哈希),会发生什么里面,那个方法被一个控制器(userController.js)调用,控制器方法(叫postRegister)调用了辅助异步方法,postRegister方法应该也是异步的吗?
  • @FelipePoncedeLeón - 正如我在回答中多次说过的那样。如果函数中有多个需要排序的异步操作,我倾向于使用async/awaittry/catch,因为代码看起来比将多个.then() 链接在一起更简单。在某些情况下,当我需要单独处理单个错误而不是一个错误处理程序来处理任何被拒绝的承诺时,我可能会使用 .catch()await。或者,您也可以为此使用多个 try/catch。您调用的函数有其自己的理由是 async 或不受 async fn 调用的影响。
  • 现在一切都清楚了,非常感谢您的时间和耐心!
猜你喜欢
  • 2019-04-06
  • 2019-03-14
  • 1970-01-01
  • 2019-09-30
  • 2018-06-21
  • 2018-10-10
  • 2021-04-10
  • 2021-08-28
  • 2017-11-23
相关资源
最近更新 更多