首页 > 解决方案 > Promise (then - catch) 或 Async / Await (with Try-Catch) 用于异常控制

问题描述

我想知道如何在 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'
            });
        }
    }
}

感谢您的时间!

标签: node.jsasync-awaittry-catch

解决方案


由于您没有提出非常具体的问题,因此我将为您的代码提供一些评论和替代方案。但首先有几点:

async使用和编程await是可选的。何时使用它部分取决于您的意见,部分取决于您在做什么。如果您的代码流中只有一个异步操作,那么通常没有特别的理由使用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()and .catch()。如果我有多个异步操作并且它们需要被序列化(一个接一个),那么我使用async/await. 这只是我的个人风格,也是我觉得最干净、最方便的风格。在其他一些情况下,async函数仅作为默认catch处理程序很有用,因此任何同步抛出的异常都会自动转换为对调用者的拒绝,并且在一些情况下,函数内部混合了同步和异步流,并且有时执行可能是完全同步的。将其包裹在一个async函数自动确保接口总是返回一个承诺,即使在某些条件下执行是完全同步的。

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


推荐阅读