@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?)-解析解析后的响应体(undefined204年)。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