# ctx 不共享问题

URL: https://caijiao.org/koa/faq/ctx
Source: docs/koa/faq/ctx.md
Description: 本文介绍了 Koa 中 'ctx' 对象的作用及其不共享问题，帮助理解如何避免多次请求之间的上下文冲突。

在 [Koa](/koa/) 中，`ctx`（上下文）对象是每个请求的上下文，它包含了请求的所有信息，如请求头、请求体、响应内容等。`ctx` 对象是每个请求的局部对象，不会在不同的请求间共享，因此每次请求都会创建一个新的 `ctx` 对象。

## 1. `ctx` 对象的作用

`ctx` 是 Koa 提供的一个非常重要的对象，它包括了以下几个方面的功能：

- **请求对象**：可以通过 `ctx.request` 获取请求相关的信息。
- **响应对象**：可以通过 `ctx.response` 设置响应。
- **请求/响应方法**：`ctx` 还提供了对请求和响应的操作方法，例如 `ctx.body`、`ctx.status` 等。
- **中间件的传递**：`ctx` 在中间件链中被传递，它允许中间件在处理请求时共享数据，但不会跨请求共享数据。

## 2. `ctx` 不共享的原因

每个 HTTP 请求都是独立的，`ctx` 对象本质上是与当前请求绑定的。每次请求都会创建一个新的 `ctx` 对象，这样就能保证不同请求之间的数据不会互相干扰或被共享。

例如，如果在第一个请求中将 `ctx` 对象上的某个属性（如 `ctx.state` 或 `ctx.body`）修改，在第二个请求中并不会受影响。

### 示例

```javascript
app.use(async (ctx, next) => {
  ctx.state.message = "Hello from first request!";
  await next();
});

app.use(async (ctx, next) => {
  console.log(ctx.state.message); // undefined in subsequent requests
  await next();
});
````

在这个例子中，`ctx.state.message` 在第一次请求中被赋值，但在随后的请求中并没有受到影响，证明了 `ctx` 对象是每个请求独立的。

## 3. 共享数据的方式

如果需要在多个请求之间共享数据，应该使用其他存储机制，比如：

- **全局存储**：例如 Redis、数据库等，适合跨请求、跨会话的数据存储。
- **Session**：可以通过 `koa-session` 中间件在多个请求之间保持用户状态。
- **请求内存缓存**：在 `ctx.state` 中存储请求间共享的数据，但这种方式仅适用于当前请求周期内的数据。

### 使用 Redis 共享数据

```javascript
const redis = require('redis');
const redisClient = redis.createClient();

app.use(async (ctx, next) => {
  const cachedData = await redisClient.getAsync('key');
  ctx.state.cachedData = cachedData;
  await next();
});
```

## 4. 避免 `ctx` 共享问题

确保在中间件中正确使用 `ctx`，避免在多个请求之间错误地共享 `ctx` 中的数据。如果你确实需要跨请求共享数据，使用合适的存储方式（如 Redis 或数据库）来确保数据的一致性和可靠性。

## 5. 总结

Koa 的 `ctx` 对象是每个请求的局部上下文，它不会在多个请求之间共享。因此，`ctx` 是安全的，不会发生数据冲突问题。然而，若你需要跨请求共享数据，应该使用合适的存储机制，如 Redis 或会话存储，来确保数据的持久性和隔离性。
