首页 ›  文章

axios 源码学习

2019-12-03

目录结构

  • catalog

其中,lib/adapters 是具体发起请求的对象,分为两个文件 http.js,xhr.js;http 适用于 node.Js 环境; xhr.js 适用于 浏览器环境;

xhr.js 采用 XMLHttpRequest 对象创建,整体遵循 这个文件中的四步;

module.exports = function bind(fn, thisArg) {
  return function wrap() {
    console.log('arguments--===');
    console.log(arguments);
    var args = new Array(arguments.length);
    for (var i = 0; i < args.length; i++) {
      args[i] = arguments[i];
    }
    return fn.apply(thisArg, args);
  };
};

这个函数的作用是 用来,改变 fn 的执行的作用域的;

无效写法

import Vue from "vue";
import axios from "axios";

axios.defaults.timeout = 5000; //响应时间
axios.defaults.headers.post["Content-Type"] =
  "application/x-www-form-urlencoded;charset=UTF-8";
axios.defaults.baseURL = process.env.VUE_APP_BASE_URL; //配置接口地址
// 添加响应拦截器
axios.interceptors.response.use(
  function (res) {
    return res;
  },
  function (error) {
    // 对响应错误做点什么
    const err = error.response.data;
    if (err.status_code === 417) {
      alert(err.message);
    } else if (err.status_code === 422) {
      for (const item in err.errors) {
        alert(err.errors[item][0]);
      }
    } else {
      alert(err.message ? err.message : "提交失败");
    }
    return Promise.resolve(error.response);
  }
);

const instance = axios.create({
  baseURL: process.env.VUE_APP_BASE_URL
})
const socialInstance = axios.create({
  baseURL: process.env.VUE_APP_SOCIAL_BASE_URL
})

export default axios;

Vue.prototype.$axios = instance;
Vue.prototype.$socailAxios = socialInstance;

怎样优化,怎能实现上述的写法呢?

待解决

给 axios 更改参数的几种形式?

本质都是修改 axios 实例的 defaults 属性内容,而实现方式都是通过 Axios.prototype.request来实现的;

  • 通过实例 defaults 属性

    axios.defaults.timeout=10000;
  • 通过直接给实例传参

    axios({
      timeout:10000
    })
  • 通过 request 来配置

    axios.request('/getUser',{
      timeout:10000
    })
  • 通过 method 别名配置

    axios.get('/getUser',{
      timeout:10000
    })

axios.create() 本身 是返回一个函数,怎样给这个函数 添加 诸如 interceptors 等属性?

通过如下

  var context = new Axios(defaultConfig);
  var instance = bind(Axios.prototype.request, context);

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

  return instance;

拦截器怎样触发的呢?

通过 promise 链

var chain = [dispatchRequest, undefined];
var promise = Promise.resolve(config);
this.interceptors.request.forEach(function unshiftRequestInterceptors(
  interceptor
) {
  chain.unshift(interceptor.fulfilled, interceptor.rejected);
});

this.interceptors.response.forEach(function pushResponseInterceptors(
  interceptor
) {
  chain.push(interceptor.fulfilled, interceptor.rejected);
});

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

return promise;

通过上述代码,实现了类似如下效果:

Promise.resolve(config).then(interceptors.request).then(dispatchRequest).then(interceptors.response).then(...)

cancelToken 怎样实现 同一个 cancel token 取消多个请求的?

通过 cancelToken 这块的代码,对于面向对象编程理解深了一步;各个文件中间,通过暴露的接口进行 通信(比如 xhr.js 和 axios 各种配置的通信);面向对象可以更好的解释这个通信过程;而如果使用 面向过程的编程方式,估计会乱成一锅粥

原文链接:segmentfault.com

上一篇:element-ui 远程搜索组件el-select在项目中组件化
下一篇:Promise 使用心得
相关文章

首次访问,人机识别验证

扫描下方二维码回复 1024 获取验证码,验证完毕后 永久 无须验证

操作步骤:[打开微信]->[扫描上侧二维码]->[关注 FedJavaScript 的微信] 输入 1024 获取验证码

验证码有误,请重新输入