Skip to content

Fetcher 客户端 API

@ahoo-wang/fetcher 包是 Fetcher 生态系统的基础。它在原生 Fetch API 之上封装了拦截器驱动的中间件管道、URL 模板解析、超时处理和类型安全的结果提取。

源码: packages/fetcher/src/fetcher.ts

Fetcher 类

主要的 HTTP 客户端类。支持所有标准 HTTP 方法,具备自动头部合并、超时解析和拦截器链处理功能。

构造函数

typescript
new Fetcher(options?: FetcherOptions)

源码: packages/fetcher/src/fetcher.ts:144

FetcherOptions

创建 Fetcher 实例的配置接口。

属性类型默认值描述
baseURLstring''添加到所有请求 URL 前的基础 URL
headersRequestHeaders{ 'Content-Type': 'application/json' }所有请求的默认头部
timeoutnumberundefined默认超时时间(毫秒)
urlTemplateStyleUrlTemplateStyleUrlTemplateStyle.PathURL 模板参数插值的风格
interceptorsInterceptorManagernew InterceptorManager()自定义拦截器管理器
validateStatusValidateStatusstatus >= 200 && status < 300响应状态验证函数

源码: packages/fetcher/src/fetcher.ts:51

实例方法

方法签名描述
fetchfetch<R>(url, request?, options?): Promise<R>主要请求方法;默认返回 Response
getget<R>(url, request?, options?): Promise<R>GET 请求(无请求体)
postpost<R>(url, request?, options?): Promise<R>POST 请求
putput<R>(url, request?, options?): Promise<R>PUT 请求
deletedelete<R>(url, request?, options?): Promise<R>DELETE 请求(无请求体)
patchpatch<R>(url, request?, options?): Promise<R>PATCH 请求
headhead<R>(url, request?, options?): Promise<R>HEAD 请求(无请求体)
optionsoptions<R>(url, request?, options?): Promise<R>OPTIONS 请求(无请求体)
tracetrace<R>(url, request?, options?): Promise<R>TRACE 请求(无请求体)
exchangeexchange(request, options?): Promise<FetchExchange>底层方法:返回完整的 exchange 对象
requestrequest<R>(request, options?): Promise<R>底层方法:使用自定义提取器的请求

源码: packages/fetcher/src/fetcher.ts:206-500

RequestOptions

属性类型描述
resultExtractorResultExtractor<any>从 exchange 中提取结果的函数
attributesRecord<string, any> | Map<string, any>用于拦截器通信的共享属性

源码: packages/fetcher/src/fetcher.ts:94

FetchRequest 和 FetchRequestInit

FetchRequestInit

单个 HTTP 请求的配置。继承原生 RequestInit 接口。

属性类型描述
methodHttpMethodHTTP 方法(GET、POST 等)
headersRequestHeaders请求级别的头部
bodyBodyInit | Record<string, any> | string | null请求体(对象会自动序列化为 JSON)
timeoutnumber请求级别的超时时间(毫秒)
urlParamsUrlParams路径和查询参数
abortControllerAbortController用于取消请求的自定义 AbortController
signalAbortSignal中止信号

源码: packages/fetcher/src/fetchRequest.ts:112

FetchRequest

FetchRequestInit 基础上增加了必需的 url 属性。

typescript
interface FetchRequest<BODY extends RequestBodyType = RequestBodyType>
  extends FetchRequestInit<BODY> {
  url: string;
}

源码: packages/fetcher/src/fetchRequest.ts:176

UrlParams

属性类型描述
pathRecord<string, any>用于 URL 模板替换的路径参数({id}:id
queryRecord<string, any>附加在 ? 之后的查询字符串参数

源码: packages/fetcher/src/urlBuilder.ts:27

NamedFetcher

Fetcher 基础上扩展了自动注册到全局 FetcherRegistrar 的功能。

typescript
const apiFetcher = new NamedFetcher('api', {
  baseURL: 'https://api.example.com',
  timeout: 5000,
});
// 之后可以通过名称获取:
const sameFetcher = fetcherRegistrar.get('api');

源码: packages/fetcher/src/namedFetcher.ts:38

一个默认的 fetcher 实例会被预先创建并导出:

typescript
import { fetcher } from '@ahoo-wang/fetcher';
fetcher.get('/users');

源码: packages/fetcher/src/namedFetcher.ts:89

FetcherRegistrar

用于管理多个命名 Fetcher 实例的注册表。

方法签名描述
registerregister(name, fetcher): void按名称注册 fetcher
unregisterunregister(name): boolean移除已注册的 fetcher
getget(name): Fetcher | undefined按名称获取 fetcher
requiredGetrequiredGet(name): Fetcher获取 fetcher,若未找到则抛出异常
default(getter)get default(): Fetcher获取默认 fetcher
default(setter)set default(fetcher)设置默认 fetcher
fetchersget fetchers(): Map<string, Fetcher>所有已注册 fetcher 的副本

源码: packages/fetcher/src/fetcherRegistrar.ts:41

InterceptorManager

管理三阶段拦截器管道:请求阶段、响应阶段和错误阶段。

属性类型描述
requestInterceptorRegistry请求阶段拦截器
responseInterceptorRegistry响应阶段拦截器
errorInterceptorRegistry错误阶段拦截器

InterceptorRegistry 方法

方法签名描述
useuse(interceptor): boolean添加拦截器(通过唯一名称)
ejecteject(name): boolean按名称移除拦截器
clearclear(): void移除所有拦截器
interceptintercept(exchange): Promise<void>按顺序执行所有拦截器

源码: packages/fetcher/src/interceptorManager.ts:48

结果提取器

FetchExchange 转换为所需返回类型的函数。

提取器返回类型描述
ResultExtractors.ExchangeFetchExchange返回完整的 exchange 对象
ResultExtractors.ResponseResponse返回原始 Response
ResultExtractors.JsonPromise<any>将响应解析为 JSON
ResultExtractors.TextPromise<string>以文本形式返回响应
ResultExtractors.BlobPromise<Blob>以 Blob 形式返回响应
ResultExtractors.ArrayBufferPromise<ArrayBuffer>以 ArrayBuffer 形式返回响应
ResultExtractors.BytesPromise<Uint8Array>以 Uint8Array 形式返回响应

源码: packages/fetcher/src/resultExtractor.ts:131

错误类

FetcherError

所有 Fetcher 错误的基类。扩展了 Error,支持 cause 链和堆栈跟踪复制。

源码: packages/fetcher/src/fetcherError.ts:37

ExchangeError

当 exchange 过程失败时抛出。包含完整的 FetchExchange 对象以便调试。

属性类型描述
exchangeFetchExchange导致错误的 exchange

源码: packages/fetcher/src/fetcherError.ts:86

HttpStatusValidationError

当响应状态验证失败时由 ValidateStatusInterceptor 抛出。

源码: packages/fetcher/src/validateStatusInterceptor.ts:27

FetchExchange

在拦截器链中流转的容器对象。

属性 / 方法类型描述
fetcherFetcher发起请求的 Fetcher 实例
requestFetchRequest请求配置
responseResponse | undefinedHTTP 响应(fetch 之后设置)
errorError | undefined发生的任何错误
attributesMap<string, any>拦截器之间的共享属性
resultExtractorResultExtractor<any>结果提取器函数
ensureRequestHeaders()RequestHeaders懒初始化请求头部
ensureRequestUrlParams()Required<UrlParams>懒初始化 URL 参数
hasError()boolean是否存在错误
hasResponse()boolean是否存在响应
requiredResponseResponse获取响应,若无则抛出 ExchangeError
extractResult<R>()Promise<R>应用结果提取器(带缓存)

源码: packages/fetcher/src/fetchExchange.ts:105

请求流程图

mermaid
flowchart TD
    A["fetcher.get('/users/{id}', { urlParams: { path: { id: 1 } } })"] --> B["Fetcher.resolveExchange()"]
    B --> C["Merge headers: fetcher.headers + request.headers"]
    C --> D["Resolve timeout: request.timeout || fetcher.timeout"]
    D --> E["Create FetchExchange"]
    E --> F["InterceptorManager.exchange()"]
    F --> G["Request Interceptors"]
    G --> G1["RequestBodyInterceptor: serialize body"]
    G1 --> G2["UrlResolveInterceptor: build URL"]
    G2 --> G3["FetchInterceptor: execute fetch()"]
    G3 --> H{"Response OK?"}
    H -->|Yes| I["Response Interceptors"]
    I --> I1["ValidateStatusInterceptor: check status"]
    H -->|No| J["Error Interceptors"]
    I1 -->|Invalid| J
    I1 -->|Valid| K["Return FetchExchange"]
    J --> J1{"Error handled?"}
    J1 -->|Yes| K
    J1 -->|No| L["Throw ExchangeError"]
    K --> M["exchange.extractResult()"]
    M --> N["Return result to caller"]

    style A fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style B fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style E fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style F fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style G fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style I fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style J fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style K fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style L fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

UrlBuilder

构建带有路径参数插值和查询字符串生成的完整 URL。

typescript
const builder = new UrlBuilder('https://api.example.com', UrlTemplateStyle.UriTemplate);
const url = builder.build('/users/{id}', {
  path: { id: 123 },
  query: { filter: 'active' }
});
// https://api.example.com/users/123?filter=active

源码: packages/fetcher/src/urlBuilder.ts:72

使用示例

基本 GET 请求

typescript
import { fetcher, ResultExtractors } from '@ahoo-wang/fetcher';

const users = await fetcher.get('/api/users', {}, {
  resultExtractor: ResultExtractors.Json,
});

带请求体和路径参数的 POST

typescript
const fetcher = new Fetcher({ baseURL: 'https://api.example.com' });

const response = await fetcher.post('/users', {
  body: { name: 'John', email: 'john@example.com' },
});

使用 URL 参数

typescript
const response = await fetcher.get('/users/{id}/posts', {
  urlParams: {
    path: { id: 123 },
    query: { page: 1, limit: 10 },
  },
});

自定义拦截器

typescript
const fetcher = new Fetcher({ baseURL: 'https://api.example.com' });

fetcher.interceptors.request.use({
  name: 'AuthInterceptor',
  order: 100,
  intercept(exchange) {
    exchange.request.headers = {
      ...exchange.request.headers,
      Authorization: `Bearer ${getToken()}`,
    };
  },
});

取消请求

typescript
const controller = new AbortController();
const response = await fetcher.get('/long-request', {
  abortController: controller,
});
// 稍后取消:
controller.abort();

NamedFetcher 注册

mermaid
classDiagram
    class Fetcher {
        +urlBuilder: UrlBuilder
        +headers: RequestHeaders
        +timeout: number
        +interceptors: InterceptorManager
        +fetch(url, request, options)
        +get(url, request, options)
        +post(url, request, options)
        +exchange(request, options)
    }
    class NamedFetcher {
        +name: string
        +constructor(name, options)
    }
    class FetcherRegistrar {
        -registrar: Map
        +register(name, fetcher)
        +get(name) Fetcher
        +default: Fetcher
        +fetchers: Map
    }

    Fetcher <|-- NamedFetcher
    NamedFetcher --> FetcherRegistrar : "auto-registers"
    FetcherRegistrar --> Fetcher : "manages"

    style Fetcher fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style NamedFetcher fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style FetcherRegistrar fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

拦截器注册

mermaid
graph TD
    subgraph sg_1 ["InterceptorManager"]
        direction TB
        subgraph sg_2 ["request: InterceptorRegistry"]
            R1["use(interceptor)"]
            R2["eject(name)"]
            R3["clear()"]
        end
        subgraph sg_3 ["response: InterceptorRegistry"]
            S1["use(interceptor)"]
            S2["eject(name)"]
        end
        subgraph sg_4 ["error: InterceptorRegistry"]
            E1["use(interceptor)"]
            E2["eject(name)"]
        end
    end

    A["Custom Interceptor<br>name, order, intercept()"] --> R1
    A --> S1
    A --> E1

    style R1 fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style S1 fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style E1 fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style A fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

相关页面

基于 Apache License 2.0 发布。