Express JS 在请求上使用异步函数

Posted

技术标签:

【中文标题】Express JS 在请求上使用异步函数【英文标题】:Express JS use async function on requests 【发布时间】:2019-01-03 06:00:28 【问题描述】:
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);
    
);

问题是。使用 async 函数可以将 await 用于 DB 查询可以吗?恐怕这会在expressjs方面引起一些问题。

【问题讨论】:

你是否故意忽略myres?否则,您可以简单地调用 next 并显示错误(如果有)(我假设您已经知道这一点)。 【参考方案1】:

async..await 是 promise 的语法糖,promise 只是一种依赖回调的模式。只要环境支持async 函数,就可以使用它们。从 Node.js 7.6.0 开始支持 async..await

async 函数总是返回一个承诺。只要这个隐式返回值不会引起问题,它在任何地方都很好,包括 Express。不管是用于数据库查询还是其他用途。

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

原始代码不包含next 调用,只是抑制了一个错误。根据经验,async 中间件的结构应该是这样的:

app.use(async function(req, res, next) 
    try 
        ...
        next();
     catch (error) 
        next(error);
    
);

【讨论】:

estus 为什么catch里面的代码包含next?正如你提到的The original code contains no next calls and just suppresses an error. 注意:如果我不使用下一个,它仍然会抛出 unhandle Promise 警告。另外,我遇​​到了这个问题:***.com/questions/13133071/… 另外,如果您也可以在这个问题上花一两分钟时间? ***.com/questions/53941672/…(会很有帮助) 抑制错误很少是个好主意。对于应该发送响应的中间件(这在 OP 中未显示),什么都不做将导致无响应和请求超时。 next 将错误委托给 Express 错误处理程序。这是在 Express 中处理错误的常用方法。您可以使用res.status(400).send(...) 而不是next(err),以防您有更具体的想法如何处理此错误。 如果我不使用 next,它仍然会抛出 unhandle Promise 警告。 - 你可能做错了什么。【参考方案2】:

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

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

const asyncMiddleware = fn =>
  (req, res, next) => 
    Promise.resolve(fn(req, res, next))
      .catch(next);
  ;

那么你可以通过以下方式使用它:

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);
));

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

app.use(function (err, req, res, next) 
   // your error code
)

【讨论】:

嗨,谢谢你的回答,你能解释一下包装器是如何工作的吗:) 我不是 javascript 专业人士,所以阅读该代码有点令人困惑 漂亮,就是太优雅了【参考方案3】:

您还可以在您的 server.ts 或 server.js 上导入 https://www.npmjs.com/package/express-async-errors 来处理 express 上的异步错误

yarn add express-async-errors

然后在你的主文件中导入import 'express-async-errors';

【讨论】:

【参考方案4】:

使用异步函数来等待数据库查询是完全可以的。但是尝试将该代码嵌入到 try 和 catch 块中,以便捕获异常。

【讨论】:

但是没有任何事情没有得到答复,它不会在快递方面引起一些不可预测的行为吗? 不会的。请看看这个博客:medium.com/@Abazhenov/…我希望它有所帮助。

以上是关于Express JS 在请求上使用异步函数的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Express 请求处理程序中编写非阻塞异步函数 [重复]

如何在 Express 请求处理程序中编写非阻塞异步函数 [重复]

在 express.js 启动之前运行异步函数

从 node.js/express.js 中的多个异步源构建对象

请求正文未从 aws-serverless-express 模块进入 app.js 文件

浅谈对express中间件的的理解。