用了这么久的axios,没想到源码居然这么简单!

1 前言

相信做前端的同学们,应该没有人没听说过axios的鼎鼎大名吧!

用了这么久的axios,是否也会好奇axios是如何实现的呢?

今天就让我们走进axios的源码,学习这款神级工具是如何实现的吧!

2 axios的实例与请求流程

在阅读源码之前,先大概了解一下axios实例的属性和请求整体流程,带着这些概念,阅读源码可以轻松不少!

下图是axios实例属性的简图。

可以看到axios的实例上,其实主要就这三个东西:

config:配置,比如url、method、params、headers等等

interceptors :拦截器,分为请求拦截器和返回拦截器。

request:调用xhr或者http请求的方法,参数就是config

由于调用request方法的时候可以再次传入config,但是不能传入interceptors,所以拦截器一定是要在请求之前就在axios上添加好,不能临时加。

下图是axios的请求流程,其实相当简单,先了解这个流程,看源码的时候就会有方向。

3 源码文件结构解析

axios的源码都在lib文件夹下,最核心的内容在core文件夹里。

lib
│  axios.js    // 最终导出的文件
│  utils.js    // 工具类
├─adapters     // 适配器相关
│      adapters.js //适配器类
│      http.js     // node请求
│      xhr.js      // 浏览器请求
├─cancel      // 取消功能相关
│      CanceledError.js //取消异常类
│      CancelToken.js   //取消token类
│      isCancel.js      //判断是否取消
├─core       // 核心功能相关 
│      Axios.js                 // axios类
│      AxiosError.js            // axios异常类
│      AxiosHeaders.js          // 请求头
│      buildFullPath.js         // 构造请求地址
│      dispatchRequest.js       // 发送请求方法
│      InterceptorManager.js    // 拦截器的类
│      mergeConfig.js           // 合并配置方法
│      settle.js                // 处理请求结果方法
│      transformData.js         // 数据转换执行方法
├─defaults    // 默认配置
│      index.js                 // 默认请求参数配置
│      transitional.js          // 默认transitional配置
├─env        //  node环境没有FormData,
│  │  data.js
│  └─classes
│          FormData.js
├─helpers  // 各种工具类方法,看名字就可以大概猜到作用
│      AxiosTransformStream.js
│      AxiosURLSearchParams.js
│      bind.js
│      buildURL.js
│      callbackify.js
│      combineURLs.js
│      cookies.js
│      deprecatedMethod.js
│      formDataToJSON.js
│      formDataToStream.js
│      fromDataURI.js
│      HttpStatusCode.js
│      isAbsoluteURL.js
│      isAxiosError.js
│      isURLSameOrigin.js
│      null.js
│      parseHeaders.js
│      parseProtocol.js
│      readBlob.js
│      README.md
│      speedometer.js
│      spread.js
│      throttle.js
│      toFormData.js
│      toURLEncodedForm.js
│      validator.js
│      ZlibHeaderTransformStream.js
└─platform  // 为不同环境下准备的方法
    │  index.js
    ├─browser
    │  │  index.js
    │  └─classes
    │          Blob.js
    │          FormData.js
    │          URLSearchParams.js
    └─node
        │  index.js
        └─classes
                FormData.js
                URLSearchParams.js

4 源码文件阅读

4.1 入口文件 axios.js

该文件创建了一个axios实例,并且导出,所以我们import axios from 'axios'引入的就是该实例,可以直接使用,不需要再new Axios({...})这样写。

下面看一下axios实例是如何创建的吧~

// 核心方法,根据config创建axios实例
function createInstance (defaultConfig) {
  // 创建axios实例
  const context = new Axios(defaultConfig);
  // 给Axios原型上的request方法绑定context为它的this
  // 这个instance就是我们最终使用的axios
  // 没想到吧,最开始的instance其实是个函数,
  // 所以我们才可以使用这个用法axios('/api/url')
  // 只不过后面给它扩展了很多东西
  const instance = bind(Axios.prototype.request, context);

  // 将Axios.prototype上的属性都绑定到instance上,
  // 这样它就拥有了简写的请求方法,比如axios.get(),axios.post()
  // 如果是函数,this绑定为context
  utils.extend(instance, Axios.prototype, context, { allOwnKeys: true });

  // 将context上的属性都绑定到instance上,
  // 这样它就拥有了拦截器属性,可以使用axios.interceptors.request.use()
  // 因为context上的函数的this本就指向context,所以第三个参数不需要再指定
  utils.extend(instance, context, null, { allOwnKeys: true });

  // 给instance增加create方法,可以通过create创建一个实例
  instance.create = function create (instanceConfig) {
    // 入参为拼接配置项,以instanceConfig为优先
    return createInstance(mergeConfig(defaultConfig, instanceConfig));
  };

  return instance;
}

// 调用上面的方法,最终导出的是axios,
// 其实是Axios.prototype.request,并扩展了很多属性
const axios = createInstance(defaults);

// 继续给axios增加属性
// 这就说明如果自己通过const myAxios=axios.create({});
// 创建出来的实例就没有下面这些属性了
// 所以下面这些属性只能通过import axios from 'axios';
// axios.all()这样的方式来使用

axios.Axios = Axios
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值