export interface IRequestOptions {
method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
headers?: { [key: string]: string };
body?: BodyInit;
}
// 添加泛型
export async function request<T>(url: string, options: IRequestOptions = {}): Promise<T> {
const response = await fetch(url, {
method: options.method || 'GET',
headers: options.headers || {
'Content-Type': 'application/json',
},
body: options.body,
});
if (!response.ok) {
throw new Error(`Request failed with status code ${response.status}`);
}
const data = (await response.json()) as T;
return data;
}
实际应用
import { paramsType, resType } from './type';
import { request } from '@/utils/request';
export async function feedbackSubmit(params: paramsType): Promise<resType> {
const data: resType = await request('https://api.example.com/data', {
method: 'POST',
body: JSON.stringify(params),
});
return data;
}
上面的feedbackSubmit请求方法是一个异步请求,如果向下面这样:
setLoading(true);
try {
feedbackSubmit(contactMsg).then((res) => {
if (res.code === 0) {
message.success(contact.status.success);
} else if (res.code === 101) {
message.error(contact.status.throttle);
} else {
message.error(contact.status.fail);
}
setLoading(false);
});
} catch {
message.error(contact.status.fail);
setLoading(false);
return;
}
如果接口报错,那么应该是 feedbackSubmit() 方法抛出了一个错误,并且没有被处理。在此情况下,try catch 是不能捕捉到这个错误的,因为它只能处理同步异常。而 feedbackSubmit() 方法是一个异步方法,所以你需要在回调函数中处理异常。你可以在then的第二个参数中传入回调函数,处理接口报错的情况。例如:
setLoading(true);
feedbackSubmit(contactMsg)
.then((res) => {
if (res.code === 0) {
message.success(contact.status.success);
} else if (res.code === 101) {
message.error(contact.status.throttle);
} else {
message.error(contact.status.fail);
}
setLoading(false);
})
.catch(() => {
message.error(contact.status.fail);
setLoading(false);
});
添加拦截器的代码
export interface IRequestOptions {
method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
headers?: { [key: string]: string };
body?: BodyInit;
}
// 定义拦截器的接口
interface Interceptor<T> {
onFulfilled?: (value: T) => T | Promise<T>;
onRejected?: (error: any) => any;
}
// 定义拦截器管理类--用于管理多个拦截器,可以通过use()方法向拦截器数组中添加一个拦截器,可以通过forEach()方法对所有的拦截器进行遍历和执行。
class InterceptorManager<T> {
private interceptors: Array<Interceptor<T>>;
constructor() {
this.interceptors = [];
}
use(interceptor: Interceptor<T>) {
this.interceptors.push(interceptor);
}
forEach(fn: (interceptor: Interceptor<T>) => void) {
this.interceptors.forEach((interceptor) => {
if (interceptor) {
fn(interceptor);
}
});
}
}
// 添加拦截器的 request 函数
export async function request<T>(url: string, options: IRequestOptions = {}): Promise<T> {
const requestInterceptors = new InterceptorManager<IRequestOptions>();
const responseInterceptors = new InterceptorManager<any>();
// 添加请求拦截器
requestInterceptors.use({
onFulfilled: (options) => {
// 处理请求
console.log('请求拦截器:处理请求');
return options;
},
onRejected: (error) => {
console.log('请求拦截器:处理错误', error);
return error;
},
});
// 添加响应拦截器
responseInterceptors.use({
onFulfilled: (response) => {
// 处理响应
console.log('响应拦截器:处理响应');
return response.json();
},
onRejected: (error) => {
console.log('响应拦截器:处理错误', error);
return error;
},
});
// 处理请求拦截器--遍历所有的请求拦截器,并执行onFulfilled()方法,将返回值赋值给options
requestInterceptors.forEach(async (interceptor) => {
options = await interceptor.onFulfilled?.(options) ?? options;
});
let response = await fetch(url, {
method: options.method || 'GET',
headers: options.headers || {
'Content-Type': 'application/json',
},
body: options.body,
});
if (!response.ok) {
throw new Error(`Request failed with status code ${response.status}`);
}
// 处理响应拦截器--遍历所有的响应拦截器,并执行onFulfilled()方法,将返回值赋值给response
responseInterceptors.forEach((interceptor) => {
response = interceptor.onFulfilled?.(response) ?? response;
});
return response.json() as Promise<T>;
}
这段代码是一个封装了拦截器的 fetch 请求函数,通过调用 request 函数可以发送请求,并对请求和响应进行拦截和处理。
具体来说,定义了一个 IRequestOptions 接口来表示请求参数,指定了请求方法和请求头等参数;定义了一个 Interceptor 类型来表示拦截器,其中包括 onFulfilled 和 onRejected 两个方法,分别表示请求成功和请求失败后的处理函数;定义了一个 InterceptorManager 类来管理拦截器数组,其中包括 use 添加拦截器和 forEach 遍历拦截器的方法。
在 request 函数中,先创建了请求拦截器和响应拦截器,使用 use 方法添加拦截器,并在请求拦截器中处理请求,在响应拦截器中处理响应。最后返回处理后的响应数据。