fetch封装
- fetch基本请求
- 接口超时 通过AbortController来实现
import type { service } from "./../../api/config";
import { config } from "@/api/config";
import { handleCode } from "./code";
import { formatToken, getToken } from "../auth";
import { ElMessage } from "element-plus";
export type ResponseData<T> = {
code: number;
data: T;
message?: string;
};
type Base = keyof service;
export interface RequestOptions extends Partial<RequestInit> {
formData?: FormData;
isBlob?: boolean;
timeout?: number;
}
export function getOptions(options?: RequestOptions): RequestInit {
const token = getToken();
const headers: Record<string, string> = {
authorization: token ? formatToken(token) : ""
};
if (options?.formData) {
options.body = options.formData;
} else {
headers["Content-Type"] = "application/json";
}
const defaultOptions: RequestInit = {
method: "GET",
headers
};
return { ...defaultOptions, ...options };
}
function timeoutPromise(timeout: number, signal: AbortSignal): Promise<never> {
return new Promise((_, reject) => {
const timeoutId = setTimeout(() => {
reject(new Error(`请求超时 ${timeout}ms`));
}, timeout);
signal.addEventListener(
"abort",
() => {
clearTimeout(timeoutId);
},
{ once: true }
);
});
}
const defaultTimeout = 15 * 1000;
export default async <T>(
url: string,
baseUrl: Base = "MOCK",
option?: RequestOptions
): Promise<ResponseData<T>> => {
const controller = new AbortController();
const newOption = getOptions({
...option,
signal: controller.signal
});
const newUrl = config[baseUrl] + url;
try {
const fetchPromise = fetch(newUrl, newOption);
const timeout = option?.timeout ?? defaultTimeout;
const response = await Promise.race([
fetchPromise,
timeoutPromise(timeout, controller.signal)
]);
let res;
if (option?.isBlob) {
res = await response.blob();
} else {
res = await response.json();
}
if (res.code !== 0 && !option?.isBlob) {
handleCode(res);
}
return res;
} catch (error) {
controller.abort();
if (error.message?.includes("请求超时")) {
ElMessage.error(error.message);
} else {
ElMessage.error("服务繁忙,请稍后再试");
}
return Promise.reject(error);
}
};