无法在包罗万象的中间件中捕获 Sequelize 抛出的错误

Unable to catch error thrown by Sequelize in a catch-all Middleware

我在一个测试项目中使用 'cls-hooked' 在 Sequelize 中启用了 CLS 事务控制,只是为了了解它的要点。 所以它在命令行和 Express 中工作得很好,事务被自动注入和管理,并且它会在任何错误时回滚。

在下面您可以看到代码在 Express 中变得多么简单,我只是将对服务层的调用包装在一个单独的 sequelize 事务函数中。到目前为止一切顺利...

router.post('/', (req, res) => {

    sequelize.transaction(async () => {

        res.status(201).json(await
            CountryService().add(req.body));

    });
});
router.post('/', async (req, res) => {

    sequelize.transaction(async () => {

        res.status(201).json(await
            CountryService().add(req.body));

    });
});

现在问题变成了错误处理。我不想 ".catch(error => { 'do error related stuff here'; })" 每个端点(更不用说与 Sequelize 相关的错误 'leak' 来自 Express,例如,'Connection Refused.' 如果我无法访问 DBMS)。

我想要一个“包罗万象的中间件”来处理这一切。

在我的其他项目中,未启用 CLS 管理的事务(因此,我自己提交和回滚,以及将事务实例传递给每个 Sequelize 调用),我可以传递我的错误中间件Express 并且它可以很好地处理任何意外情况,甚至 'express-async-errors' 也能很好地衡量。

现在,有或没有 'express-async-errors',有或没有端点异步(正如你在上面看到的,'sync' 和 'async' 版本),我得到那些可怕的(节点:2528)UnhandledPromiseRejectionWarning:错误。

具有以下内容:

UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). 
To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:2528) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

我的服务函数和端点都在堆栈跟踪中,如下所示:

at async Object.add (C:\Users\...\VSCode\sqlize-test\services\country.js:9:16)
at async C:\Users\...\VSCode\sqlize-test\routes\country.js:10:30

所以我们可以说它理解错误发生在我的服务层内,而不是跳转到我的 controller/rest/api 层。

问题是,为什么我的“catch-all middleware”抓不到它? 它是相同的中间件,与我在其他项目中使用的相同配置,没有 CLS 的嵌套事务,所以我在这里有点迷路。

为了引发错误,我通过 POST 同一个国家发送了两次,因此它违反了唯一密钥,但它会在 sequelize 验证错误和其他任何错误中发生。

感谢您的关注。

假设 catch all middleware 类似于:

  app.use(function (err, req, res, next) {
    logger.error(err)

    res.status(500).send(`<pre>${err.stack}</pre>`)
  })

您只需要从异步数据库调用中获取异常:

router.post('/', async (req, res) => {
    await sequelize.transaction(async () => {

        res.status(201).json(await
            CountryService().add(req.body));

    });
});