axios封装及其核心功能

项目中用到了axios,需要对其进行简单封装,统一数据处理和错误信息等。发现发送请求的时候可以直接实例调用,不是必须显示调用request。下面2种都可以:

const instance = axios.create({
    timeout: 5000
})
return instance({
       ...config,
})
//或者
return instance.request({
          ...config,
})

很好奇:实例在不显示调用request的情况下是怎么触发request的呢?直接浏览源码找答案吧。

1. 实例化函数之createInstance:初始化和创建实例的重要方法。
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;
}
//bind.js:是个闭包
module.exports = function bind(fn, thisArg) {
  return function wrap() {
    var args = new Array(arguments.length);
    for (var i = 0; i < args.length; i++) {
      args[i] = arguments[i];
    }
    return fn.apply(thisArg, args);
  };
};

重点:var instance = bind(Axios.prototype.request, context)
bind的返回的是个闭包函数wrap,使不同axios实例之间可以隔离作用域。
所有的请求[axios, axios.get, axios.post等...]内部调用的都是Axios.prototype.request
完美解决了开篇的疑惑。

2. 核心方法之request:返回promise

request

request方法返回promise(L54),可能是链式调用的promise,这才是axios请求真正的返回值!

那么axios可以发送哪些请求呢?看L39,一层层找:可以发送浏览器和Node请求

function getDefaultAdapter() {
  var adapter;
  if (typeof XMLHttpRequest !== 'undefined') {
    // For browsers use XHR adapter
    adapter = require('./adapters/xhr');
  } else if (typeof process !== 'undefined') {
    // For node use HTTP adapter
    adapter = require('./adapters/http');
  }
  return adapter;
}
3. 超级特性之拦截器

封装的时候经常会定义一些自己的request/response拦截器,axios是如何处理的呢?request方法里写的明明白白,回到L39:
先定义一个拦截器中间件chain,推入dispatchRequestundefined2个值。request(L43)拦截器推入头部,response(L47)拦截器推入尾部,然后通过while循环实现链式调用。

下图看起来会更加直观和清晰:


chain

总之:request拦截器先加入后执行,response拦截器先加入先执行。

参考连接

axios 核心源码实现原理
Axios 源码解析(我总觉得我解析得最全了)

看了下官网介绍axios的几大特性,排在前三的是:

  • 支持浏览器端和服务端请求
  • 支持promise
  • 支持requestresponse拦截器

本文章由javascript技术分享原创和收集

发表评论 (审核通过后显示评论):