Axios 源码分析笔记(1) — axios 初印象


Axios 简介

Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中.

读音: acks–ee–oh-ss, 中文的相似音是: 哎克 C 欧斯

此次分析的版本为 0.21.1, 压缩后 15k.

Axios 特性

  • 从浏览器创建 XMLHttpRequests
  • 拦截请求和响应
  • 转换请求和响应数据
  • 取消请求
  • 客户端支持防御XSRF

目录结构(整体印象)

|-- lib
    |-- axios.js                                     # 入口
    |-- defaults.js                                  # 默认的配置.
    |-- utils.js                                     # 通用工具类
    |-- adapters
    |   |-- http.js                                  # node环境http对象
    |   |-- README.md
    |   |-- xhr.js                                   # web环境http对象
    |-- cancel
    |   |-- Cancel.js                                # 取消的构造对象类
    |   |-- CancelToken.js                           # 取消的包装类
    |   |-- isCancel.js                              # 工具库
    |-- core
    |   |-- Axios.js                                 # Axios 类
    |   |-- buildFullPath.js                         # 根据baseURL 和 requestedURL拼接一个新的URL
    |   |-- createError.js                           # 创建异常消息的工具类
    |   |-- dispatchRequest.js                       # 触发请求
    |   |-- enhanceError.js                          # ?
    |   |-- InterceptorManager.js                    # 拦截器类
    |   |-- mergeConfig.js                           # 合并配置文件
    |   |-- README.md
    |   |-- settle.js                                # 根据http-code值来resolve/reject状态
    |   |-- transformData.js                         # 数据转换工具类
    |-- helpers/                                     # 一些辅助方法
复制代码

整体上看, 四个目录, 3 个文件还是比较清晰的. 其中最外层的axios.js 为入口文件, defaults.js 为默认配置文件, 详细如上图.

初始化

import axios from 'axios'
复制代码

当页面引入 axios 发生了什么? 从入口文件看一下, 算上注释 50多行.

// 省略导入文件文件

****** 第一部分: 创建实例 **** 
/**
 * 创建axios实例
 */
function createInstance(defaultConfig) {
  var context = new Axios(defaultConfig);
  var instance = bind(Axios.prototype.request, context);

  // Copy axios.prototype to instance
  utils.extend(instance, Axios.prototype, context);

  // Copy context to instance
  utils.extend(instance, context);

  return instance;
}

// Create the default instance to be exported
var axios = createInstance(defaults);

// Expose Axios class to allow class inheritance
axios.Axios = Axios;

// Factory for creating new instances
axios.create = function create(instanceConfig) {
  return createInstance(mergeConfig(axios.defaults, instanceConfig));
};

****** 第二部分:  实例上挂载取消请求的方法. ***** 
// Expose Cancel & CancelToken
axios.Cancel = require('./cancel/Cancel');
axios.CancelToken = require('./cancel/CancelToken');
axios.isCancel = require('./cancel/isCancel');

***** 第三部分: 其他-> 挂载工具方法. all, spread isAxiosError ****
// Expose all/spread
axios.all = function all(promises) {
  return Promise.all(promises);
};
axios.spread = require('./helpers/spread');

// Expose isAxiosError
axios.isAxiosError = require('./helpers/isAxiosError');

module.exports = axios;

// 导出文件
module.exports.default = axios;

复制代码

入口文件比较简洁, 大体分成3部分, 详细如上, 下面看一下平时没怎么用过的spread API

spread 功能

spread API 主要配合 all 使用, 更加方面获取返回参数, 将数组参数,返回为单个的参数.

module.exports = function spread(callback) {
  return function wrap(arr) {
    return callback.apply(null, arr);
  };
};
复制代码
function getUserInfo() {
  return axios.get('/user/123');
}

function getMenu() {
  return axios.get('/menu');
}

axios.all([getUserInfo(), getMenu()])
.then(axios.spread((userInfo, menu) => {
    // 两个请求都完成后
}));
复制代码

如果没有这个API 需要用result[0]的形式获取第一个promise 返回的参数, 这种命名获取参数更加好理解一些.

小结

  1. 单独的功能最好能放在一起, 如cancel, adapters 目录.
  2. 类名大写. Axios, Cancel, CancelToken.
  3. spread API的用法及实现.
  4. 所有的匿名函数都起了符合功能有意义的名字
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享