首页 > 解决方案 > 在(嵌套)try/catch/finally 块中处理 nodejs 中的错误

问题描述

我正在重构我的 nodejs 代码。我正在使用 node-postgres 实现事务。我的代码现在看起来像这样:

const controller = async (req, res, next) => {
    const client = await pool.connect()

    try {

        // get the user ID out of the params in the URL
        const { user_id } = req.params

        let query, values, result

        try {
            await client.query('BEGIN')
        } catch (err) {
            throw new CustomError(err)
        }

        try {
            query = 'QUERY_1'
            values = ['VALUES_1']
            result  = await client.query(query, values)
        } catch (err) {
            throw new CustomError(err)
        }

        // handle some stuff

        try {
            query = 'QUERY_2'
            values = ['VALUES_2']
            result  = await client.query(query, values)
        } catch (err) {
            throw new CustomError(err)
        }

        // handle some more stuff

        try {
            await client.query('COMMIT')
        } catch (err) {
            throw new CustomError(err)
        }

        return res.status(200).json({ response: 'ok' })
    } catch (err) {
        await client.query('ROLLBACK')

        return next(new CustomHandleError(400, 'something_went_wrong'))
    } finally {
        client.release()
    }
}

这段代码有效,但我有一些问题。我是 nodejs 的初学者。

1)在我的'finally'块中,我将客户端释放回池中。但是当一切正常时,我会在“尝试”块中返回响应。在线我读到'finally'块总是被执行,那么在try块中返回一个(好的)响应并在finally块中释放客户端是否可以?

2)嵌套多个try catch块是否可以(或者是反模式)。原因是 node-postgres 抛出错误,但我想将所有错误返回给自定义错误处理程序,所以我首先捕获这些错误,然后在我的 CustomError 处理程序中再次抛出它们。

提前致谢!

标签: node.jstry-catchnode-postgres

解决方案


您可以大大简化您的 try/catch 处理,因为所有内部catch块都做同样的事情并且不是必需的:

const controller = async (req, res, next) => {
    const client = await pool.connect()

    try {

        // get the user ID out of the params in the URL
        const { user_id } = req.params

        let query, values, result;
        await client.query('BEGIN');
        query = 'QUERY_1'
        values = ['VALUES_1']
        result  = await client.query(query, values)

        // handle some stuff

        query = 'QUERY_2'
        values = ['VALUES_2']
        result  = await client.query(query, values)

        // handle some more stuff

        await client.query('COMMIT')
        return res.status(200).json({ response: 'ok' })
    } catch (err) {
        await client.query('ROLLBACK')
        return next(new CustomHandleError(400, 'something_went_wrong'))
    } finally {
        client.release()
    }
}

然后,针对您的问题:

1)在我的'finally'块中,我将客户端释放回池中。但是当一切正常时,我会在“尝试”块中返回响应。在线我读到'finally'块总是被执行,那么在try块中返回一个(好的)响应并在finally块中释放客户端是否可以?

是的,这是一个很好的使用finally.

2)嵌套多个try catch块是否可以(或者是反模式)。原因是 node-postgres 抛出错误,但我想将所有错误返回给自定义错误处理程序,所以我首先捕获这些错误,然后在我的 CustomError 处理程序中再次抛出它们。

没关系(当它达到特定目标时不是反模式),但在这种情况下没有必要,因为你所有的内部catch()块都做同样的事情并且都被你的外部 catch 块捕获,所以你可以保持外部捕获并摆脱所有内部捕获。如果您的所有语句在我的代码中拒绝,那么您的所有await语句都将直接转到您的外部catch,而您在上面的所有内部 catch 语句都在做所有事情,因此它们是多余的。

需要内部捕获的一些原因是:

  1. 您想要创建一个自定义错误(对于每个异步操作都不同),您将在函数的最终结果中实际使用该错误。

  2. 您想在本地“处理”错误并继续处理不同的代码路径,而不仅仅是立即返回错误。例如,您尝试加载配置文件,捕获错误,如果配置文件不存在,则使用默认值继续执行函数中的其余代码。


推荐阅读