美文网首页
4-1、接口扩展

4-1、接口扩展

作者: Eileen_1d88 | 来源:发表于2019-12-06 11:18 被阅读0次
    需求

    为了用户更加方便地使用axios,我们需要扩展一些方法

    • axios.request(config)
    • axios.get(url[, config])
    • axios.delete(url[, config])
    • axios.head(url[, config])
    • axios.options(url[, config])
    • axios.post(url[, data[, config]])
    • axios.put(url[, data[, config]])
    • axios.patch(url[, data[, config]])
      如果使用了这些方法,我们就不必一定在config中指定url,method,data这些属性了。
      从需求上看,axios不单单是一个方法,更像是一个混合对象,本身是一个方法,同时又拥有很多方法属性。接下来我们来实现这个混合对象。
    创建Axios接口
    interface Axios {
      request(config: AxiosRequestConfig): AxiosPromise
      get(url: string, config?: AxiosRequestConfig): AxiosPromise
      head(url: string, config?: AxiosRequestConfig): AxiosPromise
      delete(url: string, config?: AxiosRequestConfig): AxiosPromise
      options(url: string, config?: AxiosRequestConfig): AxiosPromise
      put(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise
      post(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise
      patch(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise
    }
    
    创建Axios类

    src/core/Axios.ts

    import { AxiosRequestConfig, AxiosPromise, Method } from "../types";
    import dispatchRequest from "./dispatchRequest";
    
    export default class Axios {
      request(config: AxiosRequestConfig): AxiosPromise {
        return dispatchRequest(config)
      }
      get(url: string, config?: AxiosRequestConfig): AxiosPromise {
        return this._requestMethod(url, 'get', config)
      }
      delete(url: string, config?: AxiosRequestConfig): AxiosPromise {
        // const newConfig = Object.assign(config || {}, {
        //   url,
        //   method: 'delete'
        // })
        // return dispatchRequest(newConfig)
        return this._requestMethod(url, 'delete', config)
      }
      head(url: string, config?: AxiosRequestConfig): AxiosPromise {
        return this._requestMethod(url, 'head', config)
      }
      options(url: string, config?: AxiosRequestConfig): AxiosPromise {
        return this._requestMethod(url, 'options', config)
      }
      put(url: string, data?: any, config?: AxiosRequestConfig,): AxiosPromise {
        return this._requestMethod(url, 'put', config, data)
      }
      post(url: string, data?: any, config?: AxiosRequestConfig,): AxiosPromise {
        return this._requestMethod(url, 'post', config, data)
      }
      patch(url: string, data?: any, config?: AxiosRequestConfig,): AxiosPromise {
        return this._requestMethod(url, 'patch', config, data)
      }
      _requestMethod(url: string, method: Method, config?: AxiosRequestConfig, data?: any) {
        const newConfig = Object.assign(config || {}, {
          url,
          method,
          data: data || null
        })
        return this.request(newConfig)
      }
    }
    

    src/axios.ts

    import Axios from './core/Axios'
    const axios = new Axios()
    export default axios
    

    但是单单这样做有一个问题,就是axios方法是可以直接像这样使用的:

    axios({...config})
    

    但是显然我们上面的实现不能达到这个目的,所以我们需要做进一步的处理。

    创建AxiosInstance接口
    interface AxiosInstance extends Axios {
      (config: AxiosRequestConfig): AxiosPromise
    }
    

    AxiosInstance继承Axios接口,那么它就是一个混合接口
    src/axios.ts

    import { AxiosInstance } from "./types";
    import Axios from './core/Axios'
    import { extend } from "./helpers/util";
    function createInstance() {
      const context = new Axios()
      const instance = Axios.prototype.request.bind(context)
      extend(instance, context)
      return instance as AxiosInstance
    }
    const axios = createInstance()
    export default axios
    

    src/healpers/util.ts

    function extend<T, U>(to: T, from: U): T & U {
      for (const key in from) {
        ;(to as T & U)[key] = from[key] as any
      }
      return to as T & U
    }
    

    拥有axios方法的instance,也获取到axios的属性方法,这样axios除了可以使用axios.get, axios.put等方法,也可以直接使用axios(config)。

    编写demo
    import axios from '../../src/index'
    
    axios({
      url: '/extend/post',
      method: 'post',
      data: {
        msg: 'hi'
      }
    })
    
    axios.request({
      url: '/extend/post',
      method: 'post',
      data: {
        msg: 'hello'
      }
    })
    
    axios.get('/extend/get')
    
    axios.options('/extend/options')
    
    axios.delete('/extend/delete')
    
    axios.head('/extend/head')
    
    axios.post('/extend/post', { msg: 'post' })
    
    axios.put('/extend/put', { msg: 'put' })
    
    axios.patch('/extend/patch', { msg: 'patch' })
    

    至此,我们支持了对axios API的扩展,把它变成了一个混合对象。官方的axios实例,除了支持axios(config)外,还支持传入2个参数axios(url, config),这里就涉及到函数重载的概念,接下来我们来实现这个功能。

    相关文章

      网友评论

          本文标题:4-1、接口扩展

          本文链接:https://www.haomeiwen.com/subject/qhkjgctx.html