@voyo/http
v4.0.0
Published
frontend fetch request library, zero runtime dependencies
Downloads
384
Readme
@voyo/http
基于原生 fetch 的轻量前端请求库,零运行时依赖,返回 Promise。
相比旧版:移除 rxjs 依赖,用 fetch 替换 XMLHttpRequest,包体积极大减小;接口从 Observable 改为 Promise,可直接 async/await 调用。
安装
npm install @voyo/http快速使用
import { VoyoHttp } from "@voyo/http";
const http = new VoyoHttp();
http.initPlugin();
// ⚠️ initPlugin() 之后再调用 setHost/setGlobalHeader/setWithCredentials
// (它们由内置的 VoyoBasePlugin 在 initPlugin 时挂载)
http.setHost("http://localhost:3000");
// 使用 async/await 调用
const { result, statusCode } = await http.fetch({
method: "get",
path: "/hello",
});请求示例
JSON body
await http.fetch({
method: "post",
path,
json: { findId: "xxx" },
});query 参数
await http.fetch({
method: "get",
path,
query: { findId: "xxx" },
});下载 / ArrayBuffer
await http.fetch({
method: "post",
path,
responseType: "arraybuffer",
});上传 FormData
await http.fetch({
method: "post",
path,
formData,
});上传 Blob
await http.fetch({
method: "post",
path,
blob,
});设置全局请求头
http.setGlobalHeader("Authorization", "Bearer xxx");withCredentials
http.setWithCredentials(false);完整 URL
上面的示例均配合 setHost 使用 path,此时请求地址为 host + path。若需临时请求一个完整地址(不依赖已配置的 host),直接传 url:
await http.fetch({
method: "get",
url: "https://other-server.com/data",
});缓存插件
import { VoyoHttp, VoyoCachePlugin } from "@voyo/http";
const http = new VoyoHttp();
http.addPlugin(new VoyoCachePlugin({ defaultExpireSeconds: 60 }));
http.initPlugin();
await http.fetch({
method: "get",
path: "/payOrder/queryList",
query: { id },
cacheOpts: {
key: `query-${id}`,
expireSeconds: 60,
onDestroy: (httpParams) =>
!!httpParams.path?.match("payOrder/submit"),
shouldCache: (result) => result.statusCode === 200,
},
});当匹配 onDestroy 条件的请求发出时,对应缓存自动失效。
中间件
后添加的中间件在外层,可拦截请求/响应、重试、加日志等:
import { VoyoHttp } from "@voyo/http";
const http = new VoyoHttp();
http.initPlugin();
// 后执行的_addMiddleware 在外层
http.addMiddleware(async (params, next) => {
const start = Date.now();
const result = await next();
console.log(`${params.httpParams.path} → ${result.statusCode} (${Date.now() - start}ms)`);
return result;
});
// 重试中间件:5xx 自动重试(timeout 会抛错,按需加 try/catch)
http.addMiddleware(async (params, next) => {
for (let i = 0; i < 3; i++) {
const result = await next();
if (result.statusCode < 500) return result;
}
throw new Error("max retries exceeded");
});next() 返回 HttpSuccessResult;抛错则中断整条链路。中间件在插件 before/after 之后执行。
插件系统
内置 VoyoBasePlugin 处理 URL/Header/Body 组装,注册后可自定义。
顺序约束:先
addPlugin(...)再initPlugin();setHost/setGlobalHeader/setWithCredentials在initPlugin()之后调用。
import { VoyoHttpPlugin } from "@voyo/http";
const myPlugin: VoyoHttpPlugin = {
name: "my-plugin",
// priority 不要超过 100,内置插件已占用 99(cache)和 100(base)
priority: 50,
before: async ({ http, httpParams }) => {
// 请求前处理
},
after: async (result) => {
// 请求后处理
result.processed = true;
},
};
http.addPlugin(myPlugin);
http.initPlugin();插件生命周期
| hook | 说明 |
|---|---|
| patchCall | 初始化时挂载方法到 http 实例 |
| before | 请求前,返回 { http } 可短路跳过发送 |
| registryHooks | 注册底层钩子(progress/afterCompletion/errorTrigger) |
| after | 请求后,可修改 result(如 statusCode、result) |
API
VoyoHttp
class VoyoHttp {
fetch(params: HttpParams): Promise<HttpSuccessResult>;
setHost(v: string): void;
setGlobalHeader(k: string, v: any, priority?: number): void;
setWithCredentials(v: boolean): void;
addPlugin(plugin: VoyoHttpPlugin): void;
removePlugin(name: string): void;
addPluginDynamic(plugin: VoyoHttpPlugin): void;
initPlugin(): void;
}HttpParams
| 字段 | 类型 | 说明 |
|---|---|---|
| method | "get" \| "post" \| "put" \| "delete" | |
| url | string | 完整 URL,与 path 互斥 |
| path | string | 相对路径,配合 setHost |
| query | Record<string, any> | query 参数 |
| json | object | JSON body,自动 stringify |
| body | BodyInit | 原始 body |
| formData | FormData | 表单 |
| blob | Blob | Blob body |
| arrayBuffer | ArrayBuffer | 二进制 body |
| headers | HttpHeaders | 自定义请求头 |
| responseType | "json" \| "text" \| "arraybuffer" \| "blob" | 默认 json |
| withCredentials | boolean | 默认 true |
| timeout | number | 毫秒 |
| cacheOpts | { key, expireSeconds?, shouldCache?, onDestroy? } | 缓存配置 |
HttpSuccessResult
{
http: Http; // 内部 req/res
result: any; // 解析后的响应体
statusCode: number; // HTTP 状态码
}测试
npm test