@basenative/fetch

中文文档
3.0.0发布于 2026/10/31Apache-2.0TypeScriptES Module构建来源已验证

基于信号的资源获取,支持缓存和SSR预加载

中文使用文档
文档目录13 节
  1. 安装
  2. 快速入门
  3. API客户端
  4. API
  5. createResource(fetcher, options?)
  6. createMutation(mutationFn, options?)
  7. createCache(options?)
  8. fetchJson(url, options?)
  9. createApiClient(选项)
  10. ApiError / isApiError(value)
  11. isApiResponse(value) / isApiErrorEnvelope(value) / unwrap(e…
  12. serializeQuery(params) / joinUrl(base, path)
  13. 许可证

@basenative /取回

基于信号的异步资源获取,包括缓存、突变、请求重复数据删除和类型化API客户端

部分 BaseNative 生态系统——基于信号的web运行时,基于原生HTML。

安装

npm install @basenative/fetch

快速入门

import { createResource, createMutation, createCache, fetchJson } from '@basenative/fetch';

// Fetch and expose reactive state
const users = createResource(() => fetchJson('/api/users'));

import { effect } from '@basenative/runtime';

effect(() => {
  if (users.loading()) console.log('Loading...');
  if (users.error()) console.error(users.error());
  if (users.data()) console.log(users.data());
});

// Refetch with params
await users.refetch({ page: 2 });

// Optimistic mutation
const createUser = createMutation(
  (data) => fetchJson('/api/users', { method: 'POST', body: data }),
  { onSuccess: () => users.refetch() }
);

await createUser.mutate({ name: 'Alice' });

API客户端

import { createApiClient, isApiError, unwrap } from '@basenative/fetch';

const api = createApiClient({
  baseUrl: 'https://api.example.com',
  headers: { 'x-app': 'demo' },
  timeoutMs: 10_000,
  onUnauthorized: () => location.assign('/login'),
});

// Bodies are JSON-encoded, responses JSON-parsed; the envelope comes back as is
const page = await api.get('/api/leads', { page: 2, status: ['new', 'open'] });
page.data; // Lead[]
page.meta; // { total, page, perPage }

// unwrap() when you only need `data`
const lead = await unwrap(api.post('/api/leads', { firstName: 'Jane' }));

try {
  await api.delete(`/api/leads/${lead.id}`);
} catch (err) {
  if (isApiError(err)) console.error(err.status, err.code, err.message);
}

每个失败-非2xx状态,和 { error: { code, message } } 包含2xx消息体、超时或网络错误的信封——拒绝使用 ApiError. 来电者自己的 AbortSignal 中止被原封不动地重新抛出,所以 createResource(() => api.get(...)) 一直忽略取消。

API

createResource(fetcher, options?)

创建基于信号的异步资源,以响应式方式获取数据。选项:

  • initialData -价值 data 在第一次取回之前。
  • immediate -是否在创建时立即获取(默认: true)。
  • key —重复数据删除缓存密钥字符串。

返回: { data, loading, error, status, fetch, refetch, mutate } -所有反应性信号加上命令式方法。

  • status -计算信号: 'idle', 'loading', 'success',或者 'error'.
  • fetch(params?) -触发一个新的获取,中止任何正在运行的请求。
  • refetch(params?) -别名 fetch.
  • mutate(value) -直接更新 data 没有取出。接受一个值或更新函数。

createMutation(mutationFn, options?)

为写操作创建基于信号的突变。选项: onSuccess(result, params), onError(err, params).

返回: { data, loading, error, status, mutate, reset }.

  • mutate(params) —执行变异功能。
  • reset() —清除数据、错误,并将状态恢复为 'idle'.

createCache(options?)

创建重复数据删除请求缓存。选项: maxAge (默认为5分钟), maxSize (默认:100条)。

返回: { get(key), set(key, data), invalidate(key?), has(key), size }.

fetchJson(url, options?)

将请求体序列化为JSON的fetch包装器设置 Content-Type: application/json,并抛出类型化的 Error 与 .status 和 .response 关于非2xx响应。

createApiClient(选项)

创建类型化 fetch 绑定到基URL的包装器。选项:

  • baseUrl -字符串,或在每次请求时解析的函数。
  • headers -每个请求都发送报头;每个请求头获胜。
  • fetch -实现使用(默认: globalThis.fetch)。
  • credentials -默认凭据模式(default: 'include')。
  • timeoutMs -中止需要更长时间的请求;他们拒绝了 ApiError 谁的 code 是 'timeout'.
  • onRequest(ctx), onResponse(ctx), onUnauthorized(error, ctx) )(以前 onError), onError(error, ctx) 等待钩子,用于验证重定向、遥测和错误跟踪。

返回一个 ApiClient:

  • get(path, params?, init?), post(path, body?, init?), put(path, body?, init?), patch(path, body?, init?), delete(path, init?) -解析解析后的响应体(undefined 204年)。 init 接受 headers, signal, credentials, raw 和( delete) params/body.
  • request({ path, method?, params?, body?, headers?, signal?, credentials?, raw? }) -一般形式; raw: true 解析 Response 本身。
  • resolveUrl(path, params?) -请求将访问的URL。

纯对象主体是json编码的 content-type: application/json 除非你设定了一个; string, FormData, URLSearchParams, Blob, ArrayBuffer,类型化数组和流不受影响地通过。

ApiError / isApiError(value)

被客户抛出,又被 unwrap(). 字段: status (无回应时为0), code (信封的 error.code,否则 http_<status>, network_error 或者 timeout), message, field (当信封上写着一个名字时), url, body (解析后的响应体)和 response ( Response(身体已被消耗)。 isApiError(value) 是一个 instanceof 警卫。

isApiResponse(value) / isApiErrorEnvelope(value) / unwrap(envelope)

响应信封的帮手- { data, meta? } 成功, { error: { code, message, field? } } 在失败。 unwrap(envelope) 返回 data 从一个信封或从一个承诺的决心,并抛出 ApiError 如果是错误信封。

serializeQuery(params) / joinUrl(base, path)

serializeQuery({ b: 1, a: ['x', 'y'], c: null }) → ?a=x&a=y&b=1 -键排序(稳定缓存键),数组重复, null/undefined 跳过,当什么都不存在时为空字符串。 joinUrl(base, path) 只与一个相连 /;空基返回 path,绝对的 http(s):// 路径按原样返回。

许可证

apache - 2.0

版本与发布记录

@basenative/fetch 共发布 11 个版本,首次发布于 2026/03/20;过去 12 个月发布了 11 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
3.0.0latest2026/10/312 天前
2.4.02026/10/268 天前
2.3.22026/10/2212 天前
2.3.12026/10/2212 天前
2.3.02026/10/2212 天前
2.2.02026/10/2113 天前

关于 @basenative/fetch 的常见问题

@basenative/fetch 是什么?

基于信号的资源获取,支持缓存和SSR预加载

如何安装 @basenative/fetch?

在项目目录运行 npm install @basenative/fetch,或使用 pnpm add / yarn add / bun add。

@basenative/fetch 支持 TypeScript 吗?

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

@basenative/fetch 支持 ESM 还是 CommonJS?

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

@basenative/fetch 可以商用吗?

@basenative/fetch 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@basenative/fetch 还在维护吗?

最新版本 3.0.0 发布于 2026/10/31(2 天前);至今共发布 11 个版本,其中过去 12 个月发布了 11 个;首次发布于 2026/03/20。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。