# @equinor/fusion-query 中文文档

规范地址：https://npmcn.com/package/%40equinor/fusion-query/

版本：7\.0\.8
npm 元数据更新时间：2026-11-12T09:54:52.441Z
中文译文更新时间：2026-11-13T20:14:27.773Z
软件包许可：ISC

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40equinor/fusion-query
原文对照：https://npmcn.com/package/%40equinor/fusion-query/?lang=original
项目主页：https://github.com/equinor/fusion-framework/tree/master/packages/observable#readme
源码仓库：https://github.com/equinor/fusion-framework

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：408 kB，94 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：5 个
- peer 依赖：react ^18\.0\.0 \|\| ^19\.0\.0，@types/react ^18\.0\.0 \|\| ^19\.0\.0
- 首次发布：2022-12-01T11:08:40.319Z
- 最新版本发布：2026-11-12T09:54:52.118Z
- 近 30 天下载量：12873（2026-10-14 至 2026-11-12，npm 官方下载统计）
- 已发布版本数：115（近 12 个月 19 个）

## 中文简介

用可观测流和综合事件系统获取和缓存数据

## 安装

```sh
npm install @equinor/fusion-query
```

也可以使用：`pnpm add @equinor/fusion-query`、`yarn add @equinor/fusion-query`、`bun add @equinor/fusion-query`

## README

# @ equinor/ 聚变- query

反应数据取取和缓存库建于RxJS可观测器上,有队列策略,自动重试,以及综合事件系统.

## 何时使用

使用 `@equinor/fusion-query` 当您需要时:

-   用内置缓存获取远程数据, 防止冗余的网络请求
-   以可配置的队列策略管理同时提出的请求( E)`switch`, (中文(简体) ), `merge`, (中文(简体) ), `concat`(中文(简体) )
-   以自定义的延迟和计数方式自动重试失败的请求
-   对记录、调试或遥测的生命周期事件进行查询的反应
-   通过共享共享在多个消费者之间共享缓存数据 `QueryCache`
-   执行乐观的更新和缓存突变

## 安装

```bash
pnpm add @equinor/fusion-query
```

## 快速启动

```typescript
import { Query } from '@equinor/fusion-query';

interface User {
  id: string;
  name: string;
}

const userQuery = new Query<User, { id: string }>({
  client: {
    fn: async (args, signal) => {
      const res = await fetch(`/api/users/${args.id}`, { signal });
      if (!res.ok) throw new Error('Failed to fetch user');
      return res.json();
    },
  },
  key: (args) => args.id,
  expire: 60_000, // cache valid for 60 seconds
});

// Observable usage
userQuery.query({ id: '123' }).subscribe({
  next: (result) => console.log(result.value),
  error: (err) => console.error(err),
});

// Async/await usage
const result = await userQuery.queryAsync({ id: '123' });
console.log(result.value);
```

## 核心概念

### 查询

这个 `Query` 类是主要切入点。 协调 `QueryClient` (手取来),a `QueryCache` (存储结果),和一个队列运算符(控制货币). 何时 `query()` ,它首先检查缓存;如果存在有效数据,它立即发出。 否则,新抓取将被排队 .

### 查询客户端

这个 `QueryClient` 管理获取功能的执行,包括发送请求、处理故障复试和排放生命周期事件。 可以在多个领域共享 `Query` 实例.

### 查询缓存

这个 `QueryCache` 存储以生成缓存密钥键获取结果。 它支持插入,突变,无效,修饰,并重置. 多个 `Query` 实例可以共享一个用于跨组件数据共享的缓存 .

### 查询任务

A 类 `QueryTask` 代表单一的飞行中获取操作。 任务由缓存密钥来分解:如果两个消费者同时请求相同的数据,他们共享相同的任务.

## 配置选项

这个 `QueryCtorOptions` 类型定义 a 的所有配置 `Query` 实例:

| 选项 | 类型 | 说明 |
| --- | --- | --- |
| `client` | `QueryClient | { fn, options? }` | 获取函数或已有 `QueryClient` 实例 |
| `key` | `(args) => string` | 从查询参数生成一个唯一的缓存密钥 |
| `expire` | `number` | 在缓存项被视为 stale 之前的毫秒 |
| `validate` | `(entry, args) => boolean` | 自定义用于验证缓存项的功能 |
| `cache` | `QueryCache | QueryCacheCtorArgs` | 共享缓存实例或构建器参数 |
| `queueOperator` | `'switch' | 'merge' | 'concat' | fn` | 处理同时提出的请求的战略 |

## 队列策略

队列战略确定如何处理多次同时提出的不同数据请求:

-   **`switch`** (默认):当新的请求到达时取消活动请求。 最好的搜索 - you - 类型,只有最近的结果才重要.
-   **`merge`**: 并行运行所有请求。 最好每个请求都必须独立解决.
-   **`concat`**: 队列按顺序请求. 当执行命令重要时最好.

```typescript
const query = new Query<SearchResult, { term: string }>({
  client: { fn: searchApi },
  key: (args) => args.term,
  queueOperator: 'switch', // cancel stale searches
});
```

## 快取管理

### 变异( 优化更新)

直接更新缓存数据而不进行调试. 这个 `mutate` 方法返回恢复上一个值的倒数函数:

```typescript
const undo = userQuery.mutate(
  { id: '123' },
  (current) => ({ value: { ...current!, name: 'Updated Name' }, updated: Date.now() }),
);

// Roll back if the server update fails
try {
  await updateUserOnServer('123', { name: 'Updated Name' });
} catch {
  undo();
}
```

### 无效

将特定条目或整个缓存标为 stale, 强制在下一个查询上重排 :

```typescript
userQuery.invalidate({ id: '123' }); // invalidate one entry
userQuery.invalidate();                // invalidate all entries
```

### 自定义缓存验证

以自定义逻辑覆盖默认过期验证 :

```typescript
const query = new Query<Data, Args>({
  client: { fn: fetchData },
  key: (args) => JSON.stringify(args),
  validate: (entry, args) => {
    // Consider invalid if older than 30 minutes
    return (entry.updated ?? 0) + 30 * 60_000 > Date.now();
  },
});
```

### 共享缓存

多个 `Query` 实例可以共享 a `QueryCache` 避免在组件之间重复获取:

```typescript
import { Query } from '@equinor/fusion-query';
import { QueryCache } from '@equinor/fusion-query/cache';

const sharedCache = new QueryCache();

const homepageQuery = new Query({
  client: { fn: fetchPosts },
  cache: sharedCache,
  key: () => 'posts',
});

const sidebarQuery = new Query({
  client: { fn: fetchPosts },
  cache: sharedCache,
  key: () => 'posts', // same key — reuses cached data
});
```

## 持续查询

使用 `persistentQuery` 当 UI 应实时反映缓存突变 。 与 `query()`在结果公布后完成的, `persistentQuery()` 随时更新默认的缓存条目, 继续打开订阅并重寄:

```typescript
userQuery.persistentQuery({ id: '123' }).subscribe((result) => {
  renderUser(result.value); // re-renders on cache mutation
});
```

## 事件系统

这个 `Query.event$` 可观察的集合事件来自三个来源——"查询"本身,"查询卡通"和"查询卡通"——进入一流,用于监测和调试.

### 查询事件

| 活动 | 说明 |
| --- | --- |
| `query_created` | 启动新查询 |
| `query_completed` | 查询完成( 从缓存或获取) |
| `query_connected` | 订阅者加入了现有的飞行任务 |
| `query_queued` | 处理队列中添加了一个任务 |
| `query_aborted` | 一个查询通过 `AbortSignal` |
| `query_cache_hit` | 找到有效的缓存数据 |
| `query_cache_miss` | 没有有效的缓存; 需要获取 |
| `query_cache_added` | 获取的数据被写入到缓存 |
| `query_job_created` | 创建了新的抓取工作 |
| `query_job_selected` | 队列操作员选中了任务 |
| `query_job_started` | 一个工作开始执行 |
| `query_job_closed` | 工作报名被关闭了 |
| `query_job_completed` | 工作完成且结果被缓存 |
| `query_job_skipped` | 任务被跳过( 不再被观察到) |

### 查询快捷事件

| 活动 | 说明 |
| --- | --- |
| `query_client_job_requested` | 请求带参数获取 |
| `query_client_job_executing` | 获取已启动的执行 |
| `query_client_job_completed` | 成功获取完成 |
| `query_client_job_failed` | 获取执行失败 |
| `query_client_job_canceled` | 获取已取消 |
| `query_client_job_error` | 发生了无法弥补的错误 |

### 查询缓存事件

| 活动 | 说明 |
| --- | --- |
| `query_cache_entry_set` | 设置了缓存项 |
| `query_cache_entry_inserted` | 插入了一个新的条目 |
| `query_cache_entry_removed` | 已删除一个条目 |
| `query_cache_entry_invalidated` | 条目无效 |
| `query_cache_entry_mutated` | 一个条目已变异 |
| `query_cache_trimmed` | 缓存被修剪了 |
| `query_cache_reset` | 缓存被重置 |

### 订阅事件

```typescript
import { filter } from 'rxjs';
import { QueryEvent } from '@equinor/fusion-query';
import { QueryClientEvent } from '@equinor/fusion-query/client';
import { QueryCacheEvent } from '@equinor/fusion-query/cache';

// All events
query.event$.subscribe((event) => console.log(event.type, event));

// Filter by event type
query.event$.pipe(
  filter((event) => event.type === 'query_cache_hit'),
).subscribe((event) => console.log('Cache hit:', event.data));

// Filter by event source using instanceof
const cacheEvents$ = query.event$.pipe(filter((e) => e instanceof QueryCacheEvent));
const clientEvents$ = query.event$.pipe(filter((e) => e instanceof QueryClientEvent));
const queryEvents$ = query.event$.pipe(filter((e) => e instanceof QueryEvent));
```

## 反应集成

这个 `@equinor/fusion-query/react` 子路径导出 `useDebounceQuery` 在 React 组件中获取已卸载数据的钩 :

```tsx
import { useDebounceQuery } from '@equinor/fusion-query/react';

function SearchComponent() {
  const [term, setTerm] = useState('');
  const result = useDebounceQuery(myQuery, {
    args: [{ search: term }],
    delay: 300,
  });

  return <input value={term} onChange={(e) => setTerm(e.target.value)} />;
}
```

## 运算符

这个 `operators` namespace 提供 RxJS 操作器工具 :

-   **`switchQueue`**: 当新项目到达时取消在建工程(默认策略).
-   **`mergeQueue`**: 不取消同时处理项目.
-   **`concatQueue`**:按FIFO顺序依次处理项目.
-   **`queryValue`**: 提取原始数据 `value` 从查询结果流,去除元数据.

```typescript
import { operators } from '@equinor/fusion-query';

query.query({ id: '123' }).pipe(operators.queryValue).subscribe((user) => {
  console.log(user.name); // plain User object, no wrapper
});
```

## 清理

总是不订阅查询可观察或调用 `complete()` 释放资源:

```typescript
const sub = query.query(args).subscribe((r) => console.log(r));
// Later:
sub.unsubscribe();

// Or dispose the entire Query instance:
query.complete();
```

## 子路径导出

| 路径 | 目录 |
| --- | --- |
| `@equinor/fusion-query` | `Query`,类型,运算符,事件 |
| `@equinor/fusion-query/cache` | `QueryCache`, (中文(简体) ), `QueryCacheEvent`,缓存类型 |
| `@equinor/fusion-query/client` | `QueryClient`, (中文(简体) ), `QueryClientError`, (中文(简体) ), `QueryClientEvent`,客户类型 |
| `@equinor/fusion-query/operators` | 队列运算符和 `queryValue` |
| `@equinor/fusion-query/react` | `useDebounceQuery` 钩子 |

## 常见问题

### @equinor/fusion-query 是什么？

用可观测流和综合事件系统获取和缓存数据

### 如何安装 @equinor/fusion-query？

在项目目录运行 npm install @equinor/fusion-query，或使用 pnpm add / yarn add / bun add。

### @equinor/fusion-query 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @equinor/fusion-query 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @equinor/fusion-query 可以商用吗？

@equinor/fusion-query 使用 ISC 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @equinor/fusion-query 的下载量有多少？

根据 npm 官方下载统计，@equinor/fusion-query 在 2026/10/14 – 2026/11/12 这 30 天内被下载 12,873 次，日均约 429 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @equinor/fusion-query 还在维护吗？

最新版本 7\.0\.8 发布于 2026/11/12（1 天前）；至今共发布 115 个版本，其中过去 12 个月发布了 19 个；首次发布于 2022/12/01。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

