实现axios-确定结构

236 阅读1分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动​​

确定结构

首先我们知道axios 有下面两种调用方式,作为一个函数或者作为类。

import axios from 'axios'
axios.get('/user?ID=12345')

let a= axios({
	method:'get',
	url:'/user?ID=12345',
})

还可以添加拦截器

axios.interceptors.request.use((config) => {
	config={};
    return config
});

按照上面的使用情况,如果我们直接定义下面的结构的话,可以实现上面的调用。

function axios(config) {
    this.config = config
    request.apply(this);
}

axios.get = function (config) {
    request.bind(this.config, this.interceptors);
}
axios.interceptors = []

let request = function () {
    console.log(this.config, this.interceptors)
}

但是你会发现interceptors,无法使用.

所以在Axios源码中,并不是直接抛出一个axios类或者axios函数,而是抛出一个Axios.prototype.request的实例 axios本身是一个函数,上面挂在这get post等方法以及Axios类.而且Axios.prototype 也挂在着get post 之类的请求。

定义Axios类

src\core\Axios.ts

import InterceptorManager from './InterceptorManager'
import xhr from '../adapter/xhr'
import { requestConfig } from '../types/index'

function Axios(instanceConfig?: any): void {
    this.defaults = instanceConfig;
    this.interceptors = {
        request: new InterceptorManager(),
        response: new InterceptorManager()
    };
}
Axios.prototype.request = function (config:requestConfig) {
    console.log('我是request请求')
    xhr(config)
}
Axios.prototype.get=function(config:requestConfig){
    Axios.prototype.request(config)
}
Axios.prototype.post=function(config:requestConfig){
    Axios.prototype.request(config)
}
export default Axios;

导出axios

import Axios from './core/Axios'
// axios原型挂载
function createInstance() {
    const AxiosTemp = new Axios()
	// 创建request实例,并且绑定Axios实例为上下文this
    const instance = Axios.prototype.request.bind(AxiosTemp)
    // for循环是为了将Axios.prototye上的get post方法挂载到instance上
    for (const key in Axios.prototype) {
        if (typeof Axios.prototype[key] === 'function') {
            instance[key] = Axios.prototype[key].bind(AxiosTemp)
        } else {
            instance[key] = Axios.prototype[key]
        }
    }
    // for循环是为了将Axios上的default,interceptors挂载到instance上
    for (const key in AxiosTemp) {
        if (typeof Axios[key] === 'function') {
            instance[key] = AxiosTemp[key].bind(AxiosTemp)
        } else {
            instance[key] = AxiosTemp[key]
        }
    }
    instance.Axios=Axios
    return instance

}

const axios = createInstance()
export default axios;

新建type

src\types\index.ts

export interface requestConfig {
    url:string,
    method:string
    data?:any // post的参数 ? 可选
    params?:any // get的参数 ? 可选
}

测试

  1. 执行yarn build 打包

  2. 执行yarn test 启动服务

  3. example\index.html

    <script src="../../dist/index.umd.js"></script>
    <script>
        console.dir(axios)
    </script>
    
  4. 测试结果 OK!!!