关于基于fetch封装的请求方法(包含添加拦截器)

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 方法添加拦截器,并在请求拦截器中处理请求,在响应拦截器中处理响应。最后返回处理后的响应数据。

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
下面是一个使用Typescript对fetch进行封装,并添加拦截器的例子: ```typescript interface ApiOptions { method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS'; headers?: HeadersInit; body?: BodyInit; credentials?: RequestCredentials; mode?: RequestMode; cache?: RequestCache; } interface ApiResponse<T = any> { code: number; message: string; data: T; } interface Interceptor { request?: (options: ApiOptions) => ApiOptions | Promise<ApiOptions>; response?: <T>(response: ApiResponse<T>) => ApiResponse<T> | Promise<ApiResponse<T>>; } class FetchApi { private baseUrl: string; private interceptors: Interceptor; constructor(baseUrl: string, interceptors?: Interceptor) { this.baseUrl = baseUrl; this.interceptors = interceptors || {}; } public async get<T = any>(url: string, options?: ApiOptions): Promise<ApiResponse<T>> { return await this.request<T>(url, { ...options, method: 'GET' }); } public async post<T = any>(url: string, options?: ApiOptions): Promise<ApiResponse<T>> { return await this.request<T>(url, { ...options, method: 'POST' }); } public async put<T = any>(url: string, options?: ApiOptions): Promise<ApiResponse<T>> { return await this.request<T>(url, { ...options, method: 'PUT' }); } public async delete<T = any>(url: string, options?: ApiOptions): Promise<ApiResponse<T>> { return await this.request<T>(url, { ...options, method: 'DELETE' }); } private async request<T>(url: string, options: ApiOptions): Promise<ApiResponse<T>> { const requestOptions = await this.interceptRequest(options); const requestUrl = this.baseUrl + url; const response = await fetch(requestUrl, requestOptions); const responseData = await response.json(); const apiResponse = { code: response.status, message: responseData.message, data: responseData.data }; return await this.interceptResponse(apiResponse); } private async interceptRequest(options: ApiOptions): Promise<ApiOptions> { if (this.interceptors.request) { const interceptedOptions = await this.interceptors.request(options); return interceptedOptions || options; } return options; } private async interceptResponse<T>(response: ApiResponse<T>): Promise<ApiResponse<T>> { if (this.interceptors.response) { const interceptedResponse = await this.interceptors.response(response); return interceptedResponse || response; } return response; } } ``` 在这个例子中,我们创建了一个FetchApi类,它具有get、post、put、delete四个方法,用于发送对应的请求。在构造函数中,我们传入了baseUrl和interceptors两个参数,interceptors表示拦截器对象,它包含request和response两个方法,用于在请求和响应过程中进行拦截。 在get、post、put、delete四个方法中,我们调用了request方法,并传入了对应的请求方法。request方法内部首先调用interceptRequest方法,用于拦截请求。然后使用fetch函数发送请求,并解析响应体。最后调用interceptResponse方法,用于拦截响应,并解析响应体。 在interceptRequest和interceptResponse方法中,我们判断了拦截器对象是否存在,并分别调用了request和response方法,用于进行拦截。如果拦截器对象未定义对应的方法,则直接返回原始参数。 使用方法如下: ```typescript const api = new FetchApi('https://example.com', { request: (options) => { options.headers = { 'Authorization': 'Bearer token' }; return options; }, response: (response) => { if (response.code === 401) { // 处理未授权的情况 } return response; } }); api.get('/user').then(response => { console.log(response.data); }).catch(error => { console.error(error); }); ``` 在这个例子中,我们首先创建了一个FetchApi对象,传入了baseUrl和interceptors参数。在interceptors参数中,我们定义了request和response方法,用于在请求和响应过程中进行拦截。 然后我们使用get方法发送了一个请求,并在then方法中处理响应。如果发生错误,我们则在catch方法中进行处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值