modern-fetch
v1.4.2
Published
一个基于fetch api封装的restful请求风格的简易http请求库
Maintainers
Readme
modern-fetch
一款基于 fetch API 轻封装的 HTTP 请求库,专注于 RESTful API 风格调用,零依赖,源码简洁易懂。
适用于:浏览器、Node.js >= 18、Bun、Deno、React Native。
安装
npm install modern-fetch --save类型定义
type Methods = 'POST' | 'GET' | 'PUT' | 'PATCH' | 'DELETE';
type DataType = RequestInit['body'] | Record<any, any> | number;
type HeaderType = Record<string, string>;
type IFetchOption = Omit<RequestInit, 'body' | 'method' | 'headers'>;
type ResponseType = 'json' | 'text' | 'formData' | 'blob' | 'arrayBuffer' | undefined;
type IRequestInit = RequestInit & { headers: Headers };
type RequestOption = {
headers?: HeaderType;
fetchOptions?: IFetchOption;
responseType?: ResponseType;
data?: DataType;
};
type ReqInterceptor = (requestInit: IRequestInit, url: string) => Promise<IRequestInit>;
type ResInterceptor = <T = any>(
response: Response,
responseType: ResponseType,
retry: () => Promise<T>
) => Promise<any>;
type ErrInterceptor = (err: any) => void;
type Transform = (data: any, method?: Methods, url?: string) => any;
interface IFactoryOption {
headers?: HeaderType;
fetchOptions?: IFetchOption;
reqIntcp?: ReqInterceptor;
resIntcp?: ResInterceptor;
errIntcp?: ErrInterceptor;
transform?: Transform;
}快速开始
1. 创建实例
import ModernFetch from 'modern-fetch';
const CommonHttp = new ModernFetch({
baseUrl: 'https://api.example.com',
prefix: 'v1',
headers: {
'Accept': 'application/json',
},
fetchOptions: {
credentials: 'include',
},
});| 参数 | 类型 | 说明 |
|------|------|------|
| baseUrl | string | 基础请求地址 |
| prefix | string | 请求路径前缀 |
| headers | HeaderType | 公共请求头 |
| fetchOptions | IFetchOption | 原生 fetch 配置(剔除 body/method/headers) |
| reqIntcp | ReqInterceptor | 实例请求拦截器 |
| resIntcp | ResInterceptor | 实例响应拦截器 |
| errIntcp | ErrInterceptor | 实例错误拦截器 |
| transform | Transform | 请求参数转换函数 |
2. 添加拦截器
请求拦截器 — 在请求发送前修改配置
CommonHttp.addReqIntcp(async (requestInit, url) => {
requestInit.headers.set('Authorization', 'Bearer xxxxx');
return requestInit;
});响应拦截器 — 统一处理响应数据
CommonHttp.addResIntcp(async (response, responseType, retry) => {
if (response.ok) {
switch (responseType) {
case 'json':
return await response.json();
case 'text':
return await response.text();
case 'blob':
return await response.blob();
case 'formData':
return await response.formData();
case 'arrayBuffer':
return await response.arrayBuffer();
default:
return response;
}
}
// 401 场景:刷新 token 后重试
if (response.status === 401) {
await refreshToken();
return await retry();
}
return Promise.reject(response);
});错误拦截器 — 统一处理网络/请求错误
CommonHttp.addErrIntcp((err) => {
console.error('请求失败:', err.message);
});请求参数转换器 — 在请求拦截器之前运行
CommonHttp.addTransform((data, method, url) => {
// 例如:将所有数字转为字符串
return data;
});3. 请求数据变换 (Transform)
transform 是在 reqIntcp 之前执行的函数,用于统一转换请求参数:
// 示例:将日期对象转为时间戳字符串
CommonHttp.addTransform((data, method, url) => {
if (data && data.date && data.date instanceof Date) {
data.date = data.date.toISOString();
}
return data;
});全局拦截器
多个实例共享同一套拦截逻辑时,可注册全局拦截器。当实例拦截器与全局拦截器同时存在时,优先执行实例拦截器,全局拦截器不执行。
ModernFetch.addGlobalReqIntcp(async (requestInit, url) => {
requestInit.headers.set('X-Global', 'true');
return requestInit;
});
ModernFetch.addGlobalResIntcp(async (response, responseType, retry) => {
// 全局响应处理
return response;
});
ModernFetch.addGlobalErrIntcp((err) => {
// 全局错误处理
});创建请求对象
通过 create(url) 创建基于路径的请求对象,返回的实例包含 get、post、put、patch、delete 方法。
const PostApi = CommonHttp.create('/posts');请求方法调用规则
每个请求方法接收两个参数:
- 第一个参数
data?: DataType- 若为普通对象,则作为请求参数(GET 会拼接到 URL 查询字符串,其他方法作为 body)
- 若为字符串,则追加到 URL 路径末尾
- 若为
FormData/Blob/ArrayBuffer,直接作为 body
- 第二个参数
option?: RequestOption
// GET /v1/posts
PostApi.get();
// GET /v1/posts?id=1
PostApi.get({ id: 1 });
// GET /v1/posts/hot?id=1
PostApi.get('hot', { data: { id: 1 } });
// POST /v1/posts body: { title: 'hello' }
PostApi.post({ title: 'hello' });
// POST /v1/posts/hot
PostApi.post('hot');
// POST /v1/posts/hot body: { id: 1 }
PostApi.post('hot', { data: { id: 1 } });
// POST /v1/posts FormData 上传
PostApi.post(new FormData());
// POST /v1/posts/file Blob 上传
PostApi.post('file', { data: new Blob() });
// POST /v1/posts ArrayBuffer
PostApi.post(new ArrayBuffer(0));
// 文件下载: GET /v1/posts/pic.jpg
PostApi.get('pic.jpg', { responseType: 'blob' });请求方法一览
| 方法 | 说明 |
|------|------|
| get<R>(data?, option?) | 条件查询,参数拼接到 URL 查询字符串 |
| post<R>(data?, option?) | 新增/提交 |
| put<R>(data?, option?) | 全量更新 |
| patch<R>(data?, option?) | 部分更新 |
| delete<R>(data?, option?) | 删除 |
自定义 URL 请求
request 方法绕过 baseUrl 和 prefix,直接请求指定 URL:
PostApi.request('https://other-api.com/endpoint', {
method: 'POST',
body: JSON.stringify({ key: 'value' }),
headers: { 'Content-Type': 'application/json' },
}, 'json');API 参考
class ModernFetch
| 实例方法 | 说明 |
|----------|------|
| addReqIntcp(interceptor) | 添加实例请求拦截器 |
| addResIntcp(interceptor) | 添加实例响应拦截器 |
| addErrIntcp(interceptor) | 添加实例错误拦截器 |
| addTransform(transform) | 添加请求参数转换函数 |
| create(url?) | 创建基于路径的 Request 对象 |
| 静态方法 | 说明 |
|----------|------|
| ModernFetch.addGlobalReqIntcp(interceptor) | 添加全局请求拦截器 |
| ModernFetch.addGlobalResIntcp(interceptor) | 添加全局响应拦截器 |
| ModernFetch.addGlobalErrIntcp(interceptor) | 添加全局错误拦截器 |
class Request
| 方法 | 说明 |
|------|------|
| get<R>(data?, option?) | GET 请求 |
| post<R>(data?, option?) | POST 请求 |
| put<R>(data?, option?) | PUT 请求 |
| patch<R>(data?, option?) | PATCH 请求 |
| delete<R>(data?, option?) | DELETE 请求 |
| request<R>(url, requestInit, responseType?) | 自定义 URL 请求(不受 baseUrl/prefix 影响) |
