Express JS对请求使用异步功能

Ant*_*yev 4 node.js express async-await

app.use(async function(req, res, next) {
    try {
        var myres = await new Promise((resolve, reject) => {
            mysql_connection.query("select * from Users;", (err, rows) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(rows);
                }
            });
        });
    } catch (error) {
        console.log(error);
    }
});
Run Code Online (Sandbox Code Playgroud)

问题是。使用异步功能能够将等待用于数据库查询可以吗?我担心这可能会在expressjs方面引起一些问题。

Est*_*ask 5

async..await是诺言的语法糖,诺言只是依赖回调的一种模式。async只要环境支持,就可以使用功能。async..await从Node.js 7.6.0开始受支持。

async函数总是返回一个承诺。只要此隐式返回值不会引起问题,它在包括Express在内的所有地方都很好。它是否用于数据库查询或其他任何关系都没有关系。

除非API支持Promise,否则错误应完全在async函数中处理。函数体应该被包裹try..catch以排除未处理的拒绝,这可能导致将来的Node版本出现异常。

原始代码不包含任何next调用,只是抑制了错误。根据经验,async中间件的结构应如下所示:

app.use(async function(req, res, next) {
    try {
        ...
        next();
    } catch (error) {
        next(error);
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 抑制错误很少是一个好主意。如果中间件应该发送响应(OP 中未显示),则不执行任何操作将导致无响应和请求超时。`next` 将错误委托给 Express 错误处理程序。这是 Express 中处理错误的常用方法。如果您有更具体的想法如何处理此错误,可以使用 `res.status(400).send(...)` 而不是 `next(err)`。*如果我不使用 next,它仍然会抛出 unhandle Promise 警告。* - 你可能做错了什么。 (2认同)

Wil*_*een 5

异步等待可以毫无问题地用于数据库查询。您可以使用 try catch 但是有一个更优雅的解决方案,它允许您使用 express 提供的错误处理中间件:

你用这个函数包装你的中间件:

const asyncMiddleware = fn =>
  (req, res, next) => {
    Promise.resolve(fn(req, res, next))
      .catch(next);
  };
Run Code Online (Sandbox Code Playgroud)

然后您可以通过以下方式使用它:

const asyncMiddleware = require('./utils/asyncMiddleware');

router.get('/', asyncMiddleware(async (req, res, next) => {
    /* 
      if there is an error thrown in getUserFromDb, asyncMiddleware
      will pass it to next() and express will handle the error;
    */
    const user = await getUserFromDb({ id: req.params.id })
    res.json(user);
}));
Run Code Online (Sandbox Code Playgroud)

如果抛出错误,则控制权将移交给错误处理中间件,该中间件是具有四个参数的中间件,如下所示:

app.use(function (err, req, res, next) {
   // your error code
})
Run Code Online (Sandbox Code Playgroud)

  • 嗨,感谢您的回答,能否请您解释一下包装器的工作原理:) 我不是 javascript 专家,因此阅读该代码有点令人困惑 (3认同)