如何手写实现axios拦截器管理类并实现链式调用?

2026-04-01 13:451阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2437个文字,预计阅读时间需要10分钟。

如何手写实现axios拦截器管理类并实现链式调用?

目录:axios库的拦截器使用+整体设计+拦截器管理类实现+接口定义+代码实现+链式调用实现

axios库的拦截器使用我们知道,axios是一个基于Promise的HTTP客户端,拦截器是axios提供的功能之一,用于在请求或响应被处理之前拦截它们。

整体设计为了使用axios的拦截器,我们需要设计一个拦截器管理类,该类负责注册、移除和执行拦截器。

拦截器管理类实现javascriptclass AxiosInterceptorManager { constructor(instance) { this.instance=instance; this.interceptors={ request: [], response: [] }; }

use onRequest拦截器回调函数, config) { this.interceptors.request.push(callback); this.instance.interceptors.request.use(callback, undefined); }

useOnResponse拦截器回调函数, error) { this.interceptors.response.push(callback); this.instance.interceptors.response.use(undefined, callback); }

removeInterceptor(index) { this.interceptors.request.splice(index, 1); this.interceptors.response.splice(index, 1); }}

接口定义我们需要定义一个接口,用于创建axios实例并管理拦截器。

代码实现javascriptimport axios from 'axios';

function createAxiosInstance() { const instance=axios.create(); const interceptorManager=new AxiosInterceptorManager(instance);

// 示例:添加请求拦截器 interceptorManager.useOnRequest((config)=> { // 在这里可以进行请求前的处理,如添加token等 return config; });

// 示例:添加响应拦截器 interceptorManager.useOnResponse((error)=> { // 在这里可以进行响应后的处理,如错误处理等 return Promise.reject(error); });

return { instance, interceptorManager };}

链式调用实现javascriptconst { instance, interceptorManager }=createAxiosInstance();

instance.get('/api/data') .then(response=> { console.log(response.data); }) .catch(error=> { console.error(error); });

如何手写实现axios拦截器管理类并实现链式调用?

axios库的拦截器使用我们已经知道了axios拦截器的使用方法,接下来我们可以通过拦截器管理类来使用axios的拦截器。

我们知道axios库的拦截器使用方式如下:javascriptaxios.interceptors.request.use(function (config) { // 在发送请求之前做些什么 return config;}, function (error) { // 对请求错误做些什么 return Promise.reject(error);});

axios.interceptors.response.use(function (response) { // 对响应数据做点什么 return response;}, function (error) { // 对响应错误做点什么 return Promise.reject(error);});

添加一个请求拦截器javascript// 使用拦截器管理类添加请求拦截器interceptorManager.useOnRequest((config)=> { // 在这里可以进行请求前的处理,如添加token等 return config;});

目录
  • axios库的拦截器使用
  • 整体设计
  • 拦截器管理类实现
    • 接口定义
    • 代码实现
  • 链式调用实现

    axios库的拦截器使用

    我们知道axios库的拦截器的使用方式如下:

    // 添加一个请求拦截器 axios.interceptors.request.use(function (config) { // 在发送请求之前可以做一些事情 return config; }, function (error) { // 处理请求错误 return Promise.reject(error); }); // 添加一个响应拦截器 axios.interceptors.response.use(function (response) { // 处理响应数据 return response; }, function (error) { // 处理响应错误 return Promise.reject(error); });

    axios对象上有一个interceptors对象属性,该属性又有requestresponse2 个属性,它们都有一个use方法,use方法支持 2 个参数,第一个参数类似 Promise.thenresolve函数,第二个参数类似 Promise.thenreject函数。我们可以在resolve函数和reject函数中执行同步代码或者是异步代码逻辑。

    并且我们是可以添加多个拦截器的,拦截器的执行顺序是链式依次执行的方式。对于request拦截器,后添加的拦截器会在请求前的过程中先执行;对于response拦截器,先添加的拦截器会在响应后先执行。

    axios.interceptors.request.use(config => { config.headers.test += '1' return config }) axios.interceptors.request.use(config => { config.headers.test += '2' return config })

    此外,我们也可以支持删除某个拦截器,如下:

    const myInterceptor = axios.interceptors.request.use(function () {/*...*/}) axios.interceptors.request.eject(myInterceptor)

    整体设计

    我们先用一张图来展示一下拦截器工作流程:

    整个过程是一个链式调用的方式,并且每个拦截器都可以支持同步和异步处理,我们自然而然地就联想到使用 Promise 链的方式来实现整个调用过程。

    在这个 Promise 链的执行过程中,请求拦截器resolve函数处理的是config对象,而相应拦截器resolve函数处理的是response对象。

    在了解了拦截器工作流程后,我们先要创建一个拦截器管理类,允许我们去添加 删除和遍历拦截器。

    拦截器管理类实现

    根据需求,axios拥有一个interceptors对象属性,该属性又有requestresponse2 个属性,它们对外提供一个use方法来添加拦截器,我们可以把这俩属性看做是一个拦截器管理对象。

    use方法支持 2 个参数,第一个是resolve函数,第二个是reject函数,对于resolve函数的参数,请求拦截器是AxiosRequestConfig类型的,而响应拦截器是AxiosResponse类型的;而对于reject函数的参数类型则是any类型的。

    根据上述分析,我们先来定义一下拦截器管理对象对外的接口。

    接口定义

    这里我们定义了AxiosInterceptorManager泛型接口,因为对于resolve函数的参数,请求拦截器和响应拦截器是不同的。

    export interface AxiosInterceptorManager<T> { use(resolved: ResolvedFn<T>, rejected?: RejectedFn): number eject(id: number): void } export interface ResolvedFn<T=any> { (val: T): T | Promise<T> } export interface RejectedFn { (error: any): any }

    代码实现

    import { ResolvedFn, RejectedFn } from '../types' interface Interceptor<T> { resolved: ResolvedFn<T> rejected?: RejectedFn } export default class InterceptorManager<T> { private interceptors: Array<Interceptor<T> | null> constructor() { // 拦截器数组 this.interceptors = [] } // 收集拦截器 use(resolved: ResolvedFn<T>, rejected?: RejectedFn): number { this.interceptors.push({ resolved, rejected }) return this.interceptors.length - 1 } // 遍历用户写的拦截器,并执行fn函数把拦截器作为参数传入 forEach(fn: (interceptor: Interceptor<T>) => void): void { this.interceptors.forEach(interceptor => { if (interceptor !== null) { fn(interceptor) } }) } eject(id: number): void { if (this.interceptors[id]) { // 置为null,不能直接删除 this.interceptors[id] = null } } }

    我们定义了一个InterceptorManager泛型类,内部维护了一个私有属性interceptors,它是一个数组,用来存储拦截器。该类还对外提供了 3 个方法,其中use接口就是添加拦截器到interceptors中,并返回一个id用于删除;

    forEach接口就是遍历interceptors用的,它支持传入一个函数,遍历过程中会调用该函数,并把每一个interceptor作为该函数的参数传入;eject就是删除一个拦截器,通过传入拦截器的id删除。

    链式调用实现

    当我们实现好拦截器管理类,接下来就是在Axios中定义一个interceptors属性,它的类型如下:

    interface Interceptors { request: InterceptorManager<AxiosRequestConfig> response: InterceptorManager<AxiosResponse> } export default class Axios { interceptors: Interceptors constructor() { this.interceptors = { request: new InterceptorManager<AxiosRequestConfig>(), response: new InterceptorManager<AxiosResponse>() } } }

    Interceptors类型拥有 2 个属性,一个请求拦截器管理类实例,一个是响应拦截器管理类实例。我们在实例化Axios类的时候,在它的构造器去初始化这个interceptors实例属性。

    接下来,我们修改request方法的逻辑,添加拦截器链式调用的逻辑:

    interface PromiseChain { resolved: ResolvedFn | ((config: AxiosRequestConfig) => AxiosPromise) rejected?: RejectedFn } request(url: any, config?: any): AxiosPromise { if (typeof url === 'string') { if (!config) { config = {} } config.url = url } else { config = url } // 定义一个数组,这个数组就是要执行的任务链,默认有一个真正发送请求的任务 const chain: PromiseChain[] = [{ resolved: dispatchRequest, rejected: undefined }] // 把用户定义的请求拦截器存放到任务链中,请求拦截器最后注册的最先执行,所以使用unshift方法 this.interceptors.request.forEach(interceptor => { chain.unshift(interceptor) }) // 把响应拦截器存放到任务链中 this.interceptors.response.forEach(interceptor => { chain.push(interceptor) }) // 利用config初始化一个promise let promise = Promise.resolve(config) // 遍历任务链 while (chain.length) { // 取出任务链的首个任务 const { resolved, rejected } = chain.shift()! // resolved的执行时机是就是上一个promise执行resolve()的时候,这样就形成了链式调用 promise = promise.then(resolved, rejected) } return promise }

    首先,构造一个PromiseChain类型的数组chain,并把dispatchRequest函数赋值给resolved属性;接着先遍历请求拦截器插入到chain的前面;然后再遍历响应拦截器插入到chain后面。

    接下来定义一个已经 resolve 的promise,循环这个chain,拿到每个拦截器对象,把它们的resolved函数和rejected函数添加到promise.then的参数中,这样就相当于通过 Promise 的链式调用方式,实现了拦截器一层层的链式调用的效果。

    注意我们拦截器的执行顺序,对于请求拦截器,先执行后添加的,再执行先添加的;而对于响应拦截器,先执行先添加的,后执行后添加的。

    以上就是axios 拦截器管理类链式调用手写实现及原理剖析的详细内容,更多关于axios 拦截器管理类链式调用的资料请关注易盾网络其它相关文章!

    本文共计2437个文字,预计阅读时间需要10分钟。

    如何手写实现axios拦截器管理类并实现链式调用?

    目录:axios库的拦截器使用+整体设计+拦截器管理类实现+接口定义+代码实现+链式调用实现

    axios库的拦截器使用我们知道,axios是一个基于Promise的HTTP客户端,拦截器是axios提供的功能之一,用于在请求或响应被处理之前拦截它们。

    整体设计为了使用axios的拦截器,我们需要设计一个拦截器管理类,该类负责注册、移除和执行拦截器。

    拦截器管理类实现javascriptclass AxiosInterceptorManager { constructor(instance) { this.instance=instance; this.interceptors={ request: [], response: [] }; }

    use onRequest拦截器回调函数, config) { this.interceptors.request.push(callback); this.instance.interceptors.request.use(callback, undefined); }

    useOnResponse拦截器回调函数, error) { this.interceptors.response.push(callback); this.instance.interceptors.response.use(undefined, callback); }

    removeInterceptor(index) { this.interceptors.request.splice(index, 1); this.interceptors.response.splice(index, 1); }}

    接口定义我们需要定义一个接口,用于创建axios实例并管理拦截器。

    代码实现javascriptimport axios from 'axios';

    function createAxiosInstance() { const instance=axios.create(); const interceptorManager=new AxiosInterceptorManager(instance);

    // 示例:添加请求拦截器 interceptorManager.useOnRequest((config)=> { // 在这里可以进行请求前的处理,如添加token等 return config; });

    // 示例:添加响应拦截器 interceptorManager.useOnResponse((error)=> { // 在这里可以进行响应后的处理,如错误处理等 return Promise.reject(error); });

    return { instance, interceptorManager };}

    链式调用实现javascriptconst { instance, interceptorManager }=createAxiosInstance();

    instance.get('/api/data') .then(response=> { console.log(response.data); }) .catch(error=> { console.error(error); });

    如何手写实现axios拦截器管理类并实现链式调用?

    axios库的拦截器使用我们已经知道了axios拦截器的使用方法,接下来我们可以通过拦截器管理类来使用axios的拦截器。

    我们知道axios库的拦截器使用方式如下:javascriptaxios.interceptors.request.use(function (config) { // 在发送请求之前做些什么 return config;}, function (error) { // 对请求错误做些什么 return Promise.reject(error);});

    axios.interceptors.response.use(function (response) { // 对响应数据做点什么 return response;}, function (error) { // 对响应错误做点什么 return Promise.reject(error);});

    添加一个请求拦截器javascript// 使用拦截器管理类添加请求拦截器interceptorManager.useOnRequest((config)=> { // 在这里可以进行请求前的处理,如添加token等 return config;});

    目录
    • axios库的拦截器使用
    • 整体设计
    • 拦截器管理类实现
      • 接口定义
      • 代码实现
    • 链式调用实现

      axios库的拦截器使用

      我们知道axios库的拦截器的使用方式如下:

      // 添加一个请求拦截器 axios.interceptors.request.use(function (config) { // 在发送请求之前可以做一些事情 return config; }, function (error) { // 处理请求错误 return Promise.reject(error); }); // 添加一个响应拦截器 axios.interceptors.response.use(function (response) { // 处理响应数据 return response; }, function (error) { // 处理响应错误 return Promise.reject(error); });

      axios对象上有一个interceptors对象属性,该属性又有requestresponse2 个属性,它们都有一个use方法,use方法支持 2 个参数,第一个参数类似 Promise.thenresolve函数,第二个参数类似 Promise.thenreject函数。我们可以在resolve函数和reject函数中执行同步代码或者是异步代码逻辑。

      并且我们是可以添加多个拦截器的,拦截器的执行顺序是链式依次执行的方式。对于request拦截器,后添加的拦截器会在请求前的过程中先执行;对于response拦截器,先添加的拦截器会在响应后先执行。

      axios.interceptors.request.use(config => { config.headers.test += '1' return config }) axios.interceptors.request.use(config => { config.headers.test += '2' return config })

      此外,我们也可以支持删除某个拦截器,如下:

      const myInterceptor = axios.interceptors.request.use(function () {/*...*/}) axios.interceptors.request.eject(myInterceptor)

      整体设计

      我们先用一张图来展示一下拦截器工作流程:

      整个过程是一个链式调用的方式,并且每个拦截器都可以支持同步和异步处理,我们自然而然地就联想到使用 Promise 链的方式来实现整个调用过程。

      在这个 Promise 链的执行过程中,请求拦截器resolve函数处理的是config对象,而相应拦截器resolve函数处理的是response对象。

      在了解了拦截器工作流程后,我们先要创建一个拦截器管理类,允许我们去添加 删除和遍历拦截器。

      拦截器管理类实现

      根据需求,axios拥有一个interceptors对象属性,该属性又有requestresponse2 个属性,它们对外提供一个use方法来添加拦截器,我们可以把这俩属性看做是一个拦截器管理对象。

      use方法支持 2 个参数,第一个是resolve函数,第二个是reject函数,对于resolve函数的参数,请求拦截器是AxiosRequestConfig类型的,而响应拦截器是AxiosResponse类型的;而对于reject函数的参数类型则是any类型的。

      根据上述分析,我们先来定义一下拦截器管理对象对外的接口。

      接口定义

      这里我们定义了AxiosInterceptorManager泛型接口,因为对于resolve函数的参数,请求拦截器和响应拦截器是不同的。

      export interface AxiosInterceptorManager<T> { use(resolved: ResolvedFn<T>, rejected?: RejectedFn): number eject(id: number): void } export interface ResolvedFn<T=any> { (val: T): T | Promise<T> } export interface RejectedFn { (error: any): any }

      代码实现

      import { ResolvedFn, RejectedFn } from '../types' interface Interceptor<T> { resolved: ResolvedFn<T> rejected?: RejectedFn } export default class InterceptorManager<T> { private interceptors: Array<Interceptor<T> | null> constructor() { // 拦截器数组 this.interceptors = [] } // 收集拦截器 use(resolved: ResolvedFn<T>, rejected?: RejectedFn): number { this.interceptors.push({ resolved, rejected }) return this.interceptors.length - 1 } // 遍历用户写的拦截器,并执行fn函数把拦截器作为参数传入 forEach(fn: (interceptor: Interceptor<T>) => void): void { this.interceptors.forEach(interceptor => { if (interceptor !== null) { fn(interceptor) } }) } eject(id: number): void { if (this.interceptors[id]) { // 置为null,不能直接删除 this.interceptors[id] = null } } }

      我们定义了一个InterceptorManager泛型类,内部维护了一个私有属性interceptors,它是一个数组,用来存储拦截器。该类还对外提供了 3 个方法,其中use接口就是添加拦截器到interceptors中,并返回一个id用于删除;

      forEach接口就是遍历interceptors用的,它支持传入一个函数,遍历过程中会调用该函数,并把每一个interceptor作为该函数的参数传入;eject就是删除一个拦截器,通过传入拦截器的id删除。

      链式调用实现

      当我们实现好拦截器管理类,接下来就是在Axios中定义一个interceptors属性,它的类型如下:

      interface Interceptors { request: InterceptorManager<AxiosRequestConfig> response: InterceptorManager<AxiosResponse> } export default class Axios { interceptors: Interceptors constructor() { this.interceptors = { request: new InterceptorManager<AxiosRequestConfig>(), response: new InterceptorManager<AxiosResponse>() } } }

      Interceptors类型拥有 2 个属性,一个请求拦截器管理类实例,一个是响应拦截器管理类实例。我们在实例化Axios类的时候,在它的构造器去初始化这个interceptors实例属性。

      接下来,我们修改request方法的逻辑,添加拦截器链式调用的逻辑:

      interface PromiseChain { resolved: ResolvedFn | ((config: AxiosRequestConfig) => AxiosPromise) rejected?: RejectedFn } request(url: any, config?: any): AxiosPromise { if (typeof url === 'string') { if (!config) { config = {} } config.url = url } else { config = url } // 定义一个数组,这个数组就是要执行的任务链,默认有一个真正发送请求的任务 const chain: PromiseChain[] = [{ resolved: dispatchRequest, rejected: undefined }] // 把用户定义的请求拦截器存放到任务链中,请求拦截器最后注册的最先执行,所以使用unshift方法 this.interceptors.request.forEach(interceptor => { chain.unshift(interceptor) }) // 把响应拦截器存放到任务链中 this.interceptors.response.forEach(interceptor => { chain.push(interceptor) }) // 利用config初始化一个promise let promise = Promise.resolve(config) // 遍历任务链 while (chain.length) { // 取出任务链的首个任务 const { resolved, rejected } = chain.shift()! // resolved的执行时机是就是上一个promise执行resolve()的时候,这样就形成了链式调用 promise = promise.then(resolved, rejected) } return promise }

      首先,构造一个PromiseChain类型的数组chain,并把dispatchRequest函数赋值给resolved属性;接着先遍历请求拦截器插入到chain的前面;然后再遍历响应拦截器插入到chain后面。

      接下来定义一个已经 resolve 的promise,循环这个chain,拿到每个拦截器对象,把它们的resolved函数和rejected函数添加到promise.then的参数中,这样就相当于通过 Promise 的链式调用方式,实现了拦截器一层层的链式调用的效果。

      注意我们拦截器的执行顺序,对于请求拦截器,先执行后添加的,再执行先添加的;而对于响应拦截器,先执行先添加的,后执行后添加的。

      以上就是axios 拦截器管理类链式调用手写实现及原理剖析的详细内容,更多关于axios 拦截器管理类链式调用的资料请关注易盾网络其它相关文章!