在 Express 中使用 Async/await

2025-06-07

在 Express 中使用 Async/await

你有没有注意到,在 Express 请求处理程序中写了很多异步代码?这很正常,因为你需要与数据库、文件系统和其他 API 进行通信。

当你有大量异步代码时,使用 Async/await 会很有帮助。它使你的代码更容易理解。

今天,我想分享如何在 Express 请求处理程序中使用 async/await。

注意:在继续之前,你需要了解什么是 Async/await。如果你不知道,可以阅读这篇文章了解更多信息。

在请求处理程序中使用 Async/await

要使用 Async/await,您需要在定义请求处理程序时使用async关键字。(注意:这些请求处理程序被称为“控制器”。我更喜欢称之为请求处理程序,因为请求处理程序更明确。)

app.post("/testing", async (req, res) => {
  // Do something here
});
Enter fullscreen mode Exit fullscreen mode

一旦有了async关键字,您就可以await立即在代码中执行某些操作。

app.post("/testing", async (req, res) => {
  const user = await User.findOne({ email: req.body.email });
});
Enter fullscreen mode Exit fullscreen mode

处理异步错误

假设你想通过 POST 请求创建一个用户。要创建用户,你需要传入一个firstName和一个email地址。你的 Mongoose Schema 如下所示:

const userSchema = new Schema({
  email: {
    type: String,
    required: true,
    unique: true
  },
  firstName: {
    type: String,
    required: true
  }
});
Enter fullscreen mode Exit fullscreen mode

这是您的请求处理程序:

app.post("/signup", async (req, res) => {
  const { email, firstName } = req.body;
  const user = new User({ email, firstName });
  const ret = await user.save();
  res.json(ret);
});
Enter fullscreen mode Exit fullscreen mode

现在,假设您向服务器发送一个缺少电子邮件地址的请求。

fetch('/signup', {
  method: 'post'
  headers: { 'Content-Type': 'application/json' }
  body: JSON.stringify({
    firstName: 'Zell'
  })
}
Enter fullscreen mode Exit fullscreen mode

此请求导致错误。很遗憾,Express 无法处理此错误。您将收到如下日志:

未处理的承诺拒绝警告。

要处理异步函数中的错误,您需要先捕获错误。您可以使用 来实现try/catch

app.post("/signup", async (req, res) => {
  try {
    const { email, firstName } = req.body;
    const user = new User({ email, firstName });
    const ret = await user.save();
    res.json(ret);
  } catch (error) {
    console.log(error);
  }
});
Enter fullscreen mode Exit fullscreen mode

将错误记录到控制台。

接下来,使用参数将错误传递到 Express 错误处理程序中next

app.post("/signup", async (req, res, next) => {
  try {
    const { email, firstName } = req.body;
    const user = new User({ email, firstName });
    const ret = await user.save();
    res.json(ret);
  } catch (error) {
    // Passes errors into the error handler
    return next(error);
  }
});
Enter fullscreen mode Exit fullscreen mode

如果您尚未编写自定义错误处理程序,Express 将使用其默认错误处理程序为您处理错误。(尽管我建议您编写自定义错误处理程序。您可以在此处了解更多信息)。

Express 的默认错误处理程序将:

  1. 将 HTTP 状态设置为 500
  2. 向请求者发送文本响应
  3. 在控制台中记录文本响应

将文本响应发送回请求
我使用 Postman 向服务器发送了请求。以下是服务器返回的文本响应。

将文本响应记录到控制台。
注意图中的 500 HTTP 状态日志。这说明 Express 的默认处理程序将 HTTP 状态更改为 500。该日志来自 Morgan。E在这里详细讨论了 Morgan 。

处理两个或更多异步错误

如果需要处理两个await语句,则可以编写以下代码:

app.post("/signup", async (req, res, next) => {
  try {
    await firstThing();
  } catch (error) {
    return next(error);
  }

  try {
    await secondThing();
  } catch (error) {
    return next(error);
  }
});
Enter fullscreen mode Exit fullscreen mode

这是不必要的。如果firstThing导致错误,请求将立即发送到错误处理程序。您不会触发对 的调用secondThing。如果secondThing导致错误,firstThing则不会触发错误。

这意味着:只有一个错误会被发送到错误处理程序。这也意味着我们可以将所有await语句包装在一个try/catch语句中。

app.post("/signup", async (req, res, next) => {
  try {
    await firstThing();
    await secondThing();
  } catch (error) {
    return next(error);
  }
});
Enter fullscreen mode Exit fullscreen mode

清理

每个请求处理程序中都包含一条try/catch语句,这很糟糕。它们使请求处理程序看起来比实际更复杂。

一个简单的方法是将 改为try/catchpromise。这样感觉更友好。

app.post('/signup', async(req, res, next) => {
  function runAsync () {
    await firstThing()
    await secondThing()
  }

  runAsync()
    .catch(next)
})
Enter fullscreen mode Exit fullscreen mode

但为每个 Express 处理程序都写一遍太麻烦了runAsync。我们可以把它抽象成一个包装函数,然后把这个包装函数附加到每个请求处理程序上。

function runAsyncWrapper (callback) {
  return function (req, res, next) {
    callback(req, res, next)
      .catch(next)
  }
}

app.post('/signup', runAsyncWrapper(async(req, res) => {
    await firstThing()
    await secondThing()
})
Enter fullscreen mode Exit fullscreen mode

Express 异步处理程序

您也不必runAsyncWrapper每次编写 Express 应用时都编写代码。Alexei Bazhenov创建了一个名为express-async-handler 的包,它能以更健壮的方式完成这项工作。(它确保next始终是最后一个参数)。

要使用express-async-handler,您必须先安装它:

npm install express-async-handler --save
Enter fullscreen mode Exit fullscreen mode

在您的应用中使用它:

const asyncHandler = require('express-async-handler')

app.post('/signup', asyncHandler(async(req, res) => {
    await firstThing()
    await secondThing()
})
Enter fullscreen mode Exit fullscreen mode

我不喜欢写asyncHandler。它太长了。我最明显的解决办法是缩写asyncHandlerash

如果你更精通,可以考虑使用Valeri Karpov@awaitjs/express。它为 Express 添加了和等方法,因此你不必使用getAsyncpostAsyncexpress-async-handler


感谢阅读。本文最初发布在我的博客上。如果您想阅读更多文章来帮助您成为更优秀的前端开发人员,请订阅我的新闻通讯。

文章来源:https://dev.to/zellwk/using-async-await-in-express-3p77
PREV
📄 开源促销备忘单提供 8 种语言版本
NEXT
猫鼬101