npm package: @seed-fe/batch-request
Description: A library that handles batch requests.
Author: xianghongai
Latest version: 1.0.0

# @seed-fe/batch-request

批量请求合并库，用于自动合并和缓存前端重复请求，显著减少 API 调用次数。

## 特性

- 🚀 自动合并短时间内的相同请求
- 💾 内置缓存机制，避免重复请求
- 🔄 支持自定义批处理策略
- 🎯 端点隔离，互不干扰
- 🔒 完整的 TypeScript 类型支持

## 安装

```bash
# 使用 pnpm (推荐)
pnpm add @seed-fe/batch-request

# 使用 npm
npm install @seed-fe/batch-request

# 使用 yarn
yarn add @seed-fe/batch-request
```

## 使用指南

### 1. 定义端点

推荐使用 Symbol 定义端点，这样可以避免字符串冲突，并获得更好的类型提示：

```typescript
// endpoints.ts
export const ENDPOINTS = {
  PERMISSION: Symbol('permission-service'),
  USER: Symbol('user-service'),
  ORDER: Symbol('order-service'),
} as const;
```

### 2. 创建批量请求函数

以权限检查为例，我们通常需要检查用户是否有权限访问某些资源：

```typescript
import { createBatchRequest } from '@seed-fe/batch-request';
import { ENDPOINTS } from './endpoints';

// 权限检查请求类型
type PermissionRequest = {
  userId: string;
  resourceId: string;
};

// 创建批量权限检查函数
const checkPermission = createBatchRequest({
  // 端点标识符
  endpoint: ENDPOINTS.PERMISSION,

  // 请求服务，请求和响应参数为数组
  service: async (requests: PermissionRequest[]) => {
    // 业务场景中的权限校验服务，需要请求、响应参数支持数组数据
    const response = await fetch('/api/permissions/check', {
      method: 'POST',
      body: JSON.stringify({ requests })
    });
    return response.json();
  },

  // 缓存配置（默认值）
  cache: {
    ttl: 180000,    // 缓存 3 分钟（默认值）
    enable: false    // 是否启用缓存（默认值）
  },

  // 批量配置（默认值）
  batch: {
    maxSize: 100,   // 最多合并 100 个请求（默认值）
    delay: 100      // 等待 100ms 后发送（默认值）
  },

  // 缓存键生成函数（可选）
  cacheKey: (req) => `${req.userId}:${req.resourceId}`
});

// 在组件中使用
function ResourceList() {
  const userId = 'current-user-id';
  const resources = ['resource1', 'resource2', 'resource3'];

  useEffect(() => {
    // 检查多个资源权限
    Promise.all(
      resources.map(resourceId =>
        checkPermission({ userId, resourceId })
      )
    ).then(permissions => {
      // permissions = [true, false, true]
      // 虽然发起了 3 个权限检查，但实际只会发出 1 个网络请求
      // 且结果会被缓存 3 分钟（默认值）
    });
  }, []);
}

// 在路由守卫中使用
async function checkPagePermission(userId: string, pageId: string) {
  try {
    const hasPermission = await checkPermission({ userId, resourceId: pageId });
    if (!hasPermission) {
      throw new Error('无权访问');
    }
  } catch (error) {
    // 处理错误
  }
}
```

### 3. 用户切换时的缓存处理

在单页面应用 (SPA) 中，当用户登出或切换账户时，必须清除与该用户相关的缓存，以防止数据泄露给新登录的用户。

`@seed-fe/batch-request` 提供了 `clearCache()` 函数来处理此场景。

```typescript
// 在你的登出逻辑中
import { clearCache } from '@seed-fe/batch-request';
import { ENDPOINTS } from './endpoints';

export async function logout() {
  // 1. 调用后端的登出接口
  // ...

  // 2. 清除本地用户凭证
  // ...

  // 3. 清除所有批量请求缓存
  // 推荐做法是清除所有缓存，确保无数据残留
  clearCache();

  // 如果你只想精确清除与用户相关的端点，也可以逐个清除
  // clearCache(ENDPOINTS.PERMISSION);
  // clearCache(ENDPOINTS.USER);

  // 4. 重定向到登录页
  // ...
}
```

### 4. 缓存管理

```typescript
import { clearCache, getCacheStats } from '@seed-fe/batch-request';
import { ENDPOINTS } from './endpoints';

// 当用户权限更新时，清除权限缓存
function onPermissionUpdate() {
  clearCache(ENDPOINTS.PERMISSION);
}

// 监控缓存使用情况
function monitorCache() {
  const stats = getCacheStats(ENDPOINTS.PERMISSION);
  console.log('权限缓存统计:', stats); // { total: 100, valid: 95, expired: 5 }
}
```

### 5. 强制处理批次

```typescript
import { flush } from '@seed-fe/batch-request';
import { ENDPOINTS } from './endpoints';

// 在页面切换前强制处理权限检查批次
function beforeRouteChange() {
  flush(ENDPOINTS.PERMISSION);
}
```

## 主要类型 (Key Types)

了解核心类型定义有助于更好地使用本库。

### `EndpointConfig<TInput, TOutput>`

这是定义一个端点所需的核心配置。

```typescript
type EndpointConfig<TInput, TOutput> = {
  // 端点的唯一标识符 (必需)
  endpoint: string | symbol;

  // 实际执行批量请求的服务函数 (必需)
  service: (items: TInput[]) => Promise<TOutput[]>;

  // 缓存行为配置 (可选)
  cache?: Partial<CacheConfig>;

  // 批处理行为配置 (可选)
  batch?: Partial<BatchConfig>;

  // 自定义缓存键生成函数 (可选)
  cacheKey?: (item: TInput) => string;
};
```

- `CreateBatchRequestOptions` 类型是 `EndpointConfig` 的超集，额外增加了一个可选的 `manager` 属性。

### `CacheConfig`

```typescript
type CacheConfig = {
  enable: boolean; // 是否启用缓存 (默认: true)
  ttl: number;     // 缓存过期时间 (毫秒, 默认: 180000)
};
```

### `BatchConfig`

```typescript
type BatchConfig = {
  delay: number;   // 批处理延迟时间 (毫秒, 默认: 100)
  maxSize: number; // 最大批量大小 (默认: 100)
};
```

## API

### `createBatchRequest(config)`

创建批量请求函数的核心 API。它接收一个 `config` 对象。

| 参数 | 类型 | 必需 | 描述 |
| :--- | :--- | :--- | :--- |
| `endpoint` | `string \| symbol` | 是 | 端点的唯一标识符。推荐使用 `Symbol`。 |
| `service` | `(items: T[]) => Promise<U[]>` | 是 | 处理批量请求的函数。 |
| `cache` | `Partial<CacheConfig>` | 否 | 覆盖默认的缓存配置。 |
| `batch` | `Partial<BatchConfig>` | 否 | 覆盖默认的批处理配置。 |
| `cacheKey` | `(item: T) => string` | 否 | 自定义缓存键生成函数。 |
| `manager` | `IBatchManager` | 否 | 使用自定义的 `BatchManager` 实例。 |

### 辅助函数

| 函数 | 参数 | 描述 |
| :--- | :--- | :--- |
| `clearCache(endpoint?)` | `string \| symbol` (可选) | 清除指定端点或所有端点的缓存。 |
| `getCacheStats(endpoint?)` | `string \| symbol` (可选) | 获取缓存统计信息。如果 `endpoint` 省略，则返回所有端点的 `Map`。 |
| `flush(endpoint?)` | `string \| symbol` (可选) | 立即处理指定端点或所有端点的待处理批次。 |

### 高级 API

对于需要更精细控制的高级用例，可以直接使用 `BatchManager`。

- `new BatchManager(options?)`: 创建一个新的 `BatchManager` 实例。
- `getDefaultManager()`: 获取全局唯一的 `BatchManager` 实例。
- `setDefaultManager(manager)`: 替换全局的 `BatchManager` 实例。

## 默认配置

```typescript
const DEFAULT_CONFIG = {
  batch: {
    delay: 100,     // 批处理延迟时间（毫秒）
    maxSize: 100,   // 最大批量大小
  },
  cache: {
    enable: false,  // 是否启用缓存
    ttl: 180000,    // 缓存过期时间（3 分钟）
  },
};
```

## 许可证

MIT