axios原理 ----------记一次学习成果

一:了解axios

基本概念:
axios是基于promise用于浏览器和Node.js的HTTP客户端,或者说axios是基于promise的异步Ajax请求库
特点:(gitHub有详细的介绍)
在这里插入图片描述

二:axios原理

  实质上说,axios是Axios.prototype.request函数bind()返回的函数,从功能上说,axios可以是Axios原型的实例
  axios有Axios原型上的所有方法和属性   我们从源码角度分析下axios的工作流程(粗略分析)
//创建axios新实例
function createInstance(defaultConfig) {
  var context = new Axios(defaultConfig);
  var instance = bind(Axios.prototype.request, context);

  // Copy axios.prototype to instance
  //将Axios原型对象的方法绑定到新实例(axios)上
  utils.extend(instance, Axios.prototype, context);
  
  // Copy context to instance
  //将Axios原型上的属性添加到新实例上(axios)  拦截器(interceptors)和默认配置(default)
  utils.extend(instance, context);

  return instance;
}

// 使用默认配置创建axios
var axios = createInstance(defaults);

从上述源代码可以看出axios就是Axios.prototype.request函数bind()返回的函数,既然如此,我们Axios中有什么

为请求方法提供别名
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url
    }));
  };
});

utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, data, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url,
      data: data
    }));
  };
});
request()函数
Axios.prototype.request = function request(config) {
  /*eslint no-param-reassign:0*/
  // Allow for axios('example/url'[, config]) a la fetch API
  if (typeof config === 'string') {
    config = arguments[1] || {};
    config.url = arguments[0];
  } else {
    config = config || {};
  }

  config = mergeConfig(this.defaults, config);

  // Set config.method
  if (config.method) {
    config.method = config.method.toLowerCase();
  } else if (this.defaults.method) {
    config.method = this.defaults.method.toLowerCase();
  } else {
    config.method = 'get';
  }

  // Hook up interceptors middleware
  var chain = [dispatchRequest, undefined];
  var promise = Promise.resolve(config);

  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
	 //请求拦截器头部插入,fulfilled成功回调,rejected失败回调
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });

  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
	  //响应拦截器尾部追加,fulfilled成功回调,rejected失败回调
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });

  while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift());
  }
  return promise;
};

在request函数中,使用promise将请求拦截器的回调 / dispatchRequest / 响应拦截器 串联起来。这样便符合逻辑了,执行顺序 请求拦截器—>发送请求—>响应拦截器。这也可以解释一个问题,为什么我们在添加请求拦截器时执行顺序是倒的。因为promise在串联请求拦截器时采用的是头部追加。既然其他地方都没有关于请求,我们就再去看dispatchRequest

  module.exports = function dispatchRequest(config) {
  throwIfCancellationRequested(config);

  // Ensure headers exist
  config.headers = config.headers || {};

  // Transform request data
  //转换请求数据
  config.data = transformData(
    config.data,
    config.headers,
    config.transformRequest
  );

  // Flatten headers
  config.headers = utils.merge(
    config.headers.common || {},
    config.headers[config.method] || {},
    config.headers
  );

  utils.forEach(
    ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
    function cleanHeaderConfig(method) {
      delete config.headers[method];
    }
  );

  var adapter = config.adapter || defaults.adapter;

  return adapter(config).then(function onAdapterResolution(response) {
    throwIfCancellationRequested(config);

    // 转换响应数据
    response.data = transformData(
      response.data,
      response.headers,
      config.transformResponse
    );

    return response;
  }, function onAdapterRejection(reason) {
    if (!isCancel(reason)) {
      throwIfCancellationRequested(config);

      // Transform response data
      if (reason && reason.response) {
        reason.response.data = transformData(
          reason.response.data,
          reason.response.headers,
          config.transformResponse
        );
      }
    }

    return Promise.reject(reason);
  });
};

主要是在发起请求前处理请求数据 / Adapter发送请求 / 发起请求后处理响应数据
既然如此,我们再去看看Adapter
有这样几个语句

......
var request = new XMLHttpRequest();
......
request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);
......
request.send(requestData);

到这里就清除了,axios其实就是对ajax做了封装处理

总结
axios的工作原理及流程如下:
在这里插入图片描述

三 :其他内容

**

axios与Instance:

Instance是axios.create()创建出的实例对象
相同点
Instance与axios都能发送任意方式的请求,(get/post…)
都有发送特定请求的方法
都有默认配置和拦截器配置
不同点:

axios.create = function create(instanceConfig) {
	//mergeConfig  合并
  return createInstance(mergeConfig(axios.defaults, instanceConfig));
};

Instance与axios的配置不同(config参数为空例外)
Instance没有axios新增的属性和方法 ,比如create(),CancelToken(),all(),Axios…
Instance没有取消请求和批发请求

为什么要用Instance
项目中多个接口,接口的配置不全部相同,创建两个新的instance,每个都有自己的配置,这样就很好解决

大佬勿喷,小白一只

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值