请求库也要跟上时代,从 选项式 到 组合式 改变
soon-fetch 可根据需要,自行组装的request
,没有魔法式的逻辑控制
常用的请求库如axios
,ofetch
等的一些缺陷:
- 各种
onRequest
,onResponse
,onError
,得仔细查看文档才能弄清这些选项执行的时机,把原本简单的逻辑弄复杂了。 - 限定返回类型
responseType
,使得当一个接口返回多种类型时,做了多余的转换。如导出报表接口,正常返回文件流
,但当数据量超过10万时,返回报错信息json
,提醒用户限制范围缩小数据量。默认responseType
设置为blob
,错误信息也会被转为blob
,还需要手动加条件判断转回json
.
soon-fetch的处理方式
仅提供parseUrlOptions
函数,将SoonOptions
转换为原生 fetch 的options
如有特殊需要,可以根据下方的函数定制你自己的解析函数来替代 parseUrlOptions
:
mergeHeaders
, mergeSignals
, mergeUrl
, isBodyJson
const request = <T>(url: string, options?: SoonOptions): Promise<T> => {
//合并options及baseOptions,并转换
const [_url, _options] = parseUrlOptions({
url,
options,
baseURL: "/api",
baseOptions: {
timeout: 20 * 1000,
headers: { Authorization: localStorage.getItem("token") ?? "" },
},
})
return fetch(_url, _options).then((res) => {
if (res.headers.get("content-type")?.includes("json")) {
return res.json()
}
else {
return res.blob()
}
})
}
const soon = createSoon(request);
/** GET */
soon.get("/user?id=123");
soon.get("/user", { query: { id: 123 } });
soon.get("/user/:id", { params: { id: 123 } });
/** POST */
soon.post("/login", { body: { username: "admin", password: "123456" } });
//定义一个api
export const getUserInfo=soon.API('/user/:id').GET()
//使用
getUserInfo({id:2}).then(res=>console.log(res))
- 🌐 自动解析 rest Url 的参数
- ⭐ 快捷定义请求 api
- ⌛ 超时断开
- 🔤 自动处理 JSON
- 📏 不到 2K , zip 后会更小
- 💡 用 typescript 有智能类型提醒
完整示例 (包含双token静默刷新,retry重试)
特别功能
快捷方法
soon.get(url, options);
soon.post(url, options);
soon.put(url, options);
soon.patch(url, options);
soon.delete(url, options);
soon.head(url, options);
soon.options(url, options);
Restful Url 参数自动处理
url 包含 /:key 会解析匹配 key
soon.get("/api/user/:id", { params: { id: 1 } });
// api/user/1
soon.get("/api/:job/:year", { params: { job: "engineer", year: 5 } });
//api/engineer/5
超时
//** 请求级超时, 会覆盖实例级超时 */
soon.get(url, { timeout: 1000 * 20 });
快速定义 API
//可以是 GET POST PATCH PUT DELETE
//GET 请求数据传递至query,其他方法请求数据传递至body
soon.API(url:string).POST<RequestType,ResponseType>()
//定义一个api
export const getUserInfo=soon.API('/user/:id').GET()
//使用
getUserInfo({id:2})
.then(res=>console.log(res))
.catch(err=>console.log(err))
//用typescript,
export const login=soon.API('/user/login')
.POST<{username:string,password:string},{token:string}>()
//开发工具会有请求和响应的智能提醒
login({username:'admin',password:'123'}).then(res=>{
localStorage.setItem('token', res.token);
})
API 参考
parseUrlOptions源码如下
function parseUrlOptions<Options extends SoonOptions>(urlOptions: {
url: string;
options?: Options;
baseURL?: string;
baseOptions?: Options;
}) {
const { url, options, baseURL, baseOptions } = urlOptions;
// 覆盖 baseOptions
const _options = { ...baseOptions, ...options };
// 以 AbortSignal.any 的方式合并 baseOptions.signal 、 options.signal 、
// 以及 AbortSignal.timeout( _options.timeout)
_options.signal = mergeSignals(
[baseOptions?.signal, options?.signal],
_options.timeout
);
//根据 baseURL , options.query , options.params 解析出完整的url
const _url = mergeUrl(url, { ..._options, baseURL });
// 自动stringify json-object类的body
let _body = options?.body;
let is_body_json = isBodyJson(_body);
_options.body = is_body_json ? JSON.stringify(_body) : _body;
//合并headers, 相同key值的header会被options.headers覆盖
//当body 为 json ,自动添加 header "Content-Type": "application/json" }
const headers = mergeHeaders(
baseOptions?.headers,
options?.headers,
is_body_json ? { "Content-Type": "application/json" } : undefined
);
_options.headers = headers;
return [_url, _options as Options & { headers: Headers }] as const;
}
如有特殊需要,可以根据下方的函数定制你自己的解析函数来替代 parseUrlOptions
:
mergeHeaders
, mergeSignals
, mergeUrl
, isBodyJson
SoonOptions
// function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>
// RequestInit 为原生 fetch 的 init 选项
type SoonOptions = Omit<RequestInit, "body"> & {
query?: Record<string, string | number | boolean | null | undefined | (string | number | boolean | null | undefined)[]> | URLSearchParams;
params?: Record<string, string | number>;
timeout?: number;
body?: RequestInit["body"] | object;
};
支持一下
喜欢 soon-fetch 的话 , 在 github 上给个 star 吧.
安装 Installation
npm install soon-fetch