# async 错误捕获

URL: https://caijiao.org/koa/faq/async
Source: docs/koa/faq/async.md
Description: 本文介绍了在 Koa 中使用 async/await 语法时如何进行错误捕获，确保应用的稳定性。

在 Koa 中，当你使用 `async`/`await` 语法时，错误捕获是非常重要的，因为未处理的异步错误可能会导致应用崩溃。[Koa](/koa/) 提供了不同的方式来处理 `async`/`await` 代码中的错误，确保错误能够被捕获并正确处理。

## 1. 异常捕获的基本原理

在 `async` 函数中，`await` 关键字会等待一个 Promise 对象解析。如果该 Promise 被拒绝（例如发生错误），则会抛出一个异常。你可以使用 `try-catch` 块来捕获和处理这些错误。

### 示例：使用 try-catch 捕获错误

```javascript
app.use(async (ctx, next) => {
  try {
    // 异步操作
    const data = await someAsyncFunction();
    ctx.body = data;
  } catch (err) {
    // 错误处理
    ctx.status = 500;
    ctx.body = { message: 'Internal Server Error', error: err.message };
  }
});
````

在这个例子中，我们通过 `try-catch` 块捕获了异步函数 `someAsyncFunction()` 中可能抛出的错误。如果出现错误，`catch` 语句会捕获它，并返回一个 500 错误响应。

## 2. 全局错误处理

除了在每个中间件中使用 `try-catch` 来捕获错误外，你还可以为整个应用配置一个全局的错误处理机制。在 Koa 中，可以使用 `app.on('error')` 来处理所有未捕获的错误。

### 示例：全局错误处理

```javascript
app.on('error', (err, ctx) => {
  console.error('server error', err, ctx);
  ctx.status = err.status || 500;
  ctx.body = {
    message: 'Internal Server Error',
    error: err.message,
  };
});
```

这样做可以捕获在中间件中未被捕获的错误，并统一进行处理和日志记录。

## 3. 使用异步中间件

在 Koa 中，所有的中间件都可以是异步的，但它们必须返回一个 `Promise`。当你在异步中间件中遇到错误时，必须捕获并处理该错误，以防止错误传递到下游中间件。

### 示例：异步中间件中的错误处理

```javascript
app.use(async (ctx, next) => {
  try {
    await someAsyncOperation();
    await next(); // 调用下一个中间件
  } catch (err) {
    ctx.status = 500;
    ctx.body = { message: 'Error during async operation', error: err.message };
  }
});
```

在此示例中，`someAsyncOperation()` 是一个异步操作，我们用 `try-catch` 来捕获其异常。如果发生错误，错误信息将返回给客户端。

## 4. 错误处理中间件

如果你希望对错误进行集中管理，可以创建一个专门的错误处理中间件。它将在所有中间件之后被调用，并能够捕获任何未被处理的错误。

### 示例：错误处理中间件

```javascript
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    ctx.status = err.status || 500;
    ctx.body = { message: 'Something went wrong!', error: err.message };
    // 记录错误日志
    console.error(err);
  }
});
```

这种方式确保所有错误都会被捕获并返回统一的响应。

## 5. 处理异步函数的 Promise 拒绝

当你调用异步函数并且该函数返回一个拒绝的 Promise 时，你可以在外层 `async` 函数中捕获到该错误。如果没有在 `async` 函数中捕获，错误将会被抛出并最终由 Koa 的错误处理中间件捕获。

### 示例：捕获异步操作中的错误

```javascript
app.use(async (ctx, next) => {
  const result = await someAsyncFunction().catch(err => {
    // 捕获异步函数中的错误
    ctx.status = 400;
    ctx.body = { message: 'Error in async function', error: err.message };
  });

  if (result) {
    ctx.body = result;
  }
});
```

## 6. 总结

* 使用 `try-catch` 是捕获 `async`/`await` 错误的标准方式。
* 你可以通过为应用设置全局错误处理来处理未被捕获的错误。
* 为了确保应用稳定性，合理使用错误处理机制，避免错误导致请求中断。
* 异常处理中间件能够捕获所有中间件中的错误，统一处理。

通过适当的错误捕获机制，可以确保 Koa 应用的稳定运行，并在出现错误时及时向用户提供反馈。
