从零实现axios(1.3小节-创建axios实例)

58 阅读2分钟

创建 axios 实例

我们在根目录下创建axios.js文件,文件内容如下面代码所示。

我们通过createInstance函数创建一个axios实例,该函数的核心是通过bind方法把Axios原型上的 request方法,封装到instance中,通过对 instance 函数的调用,间接调用 request方法。js中由于函数也是对象,所以我们可以把Axios原型上的方法拷贝到该函数上,这样就可以实现例如axios.get()这样的请求调用,当然现在原型上只有request方法,我们之后会往上面扩展getpost等方法

"use strict";

var utils = require("./utils");
var bind = require("./helpers/bind");
var Axios = require("./core/Axios");
var defaults = require("./defaults");

/**
 * 创建一个 Axios 实例
 *
 * @param {Object} defaultConfig 实例的默认配置
 * @return {Axios} Axios的新实例
 */
function createInstance(defaultConfig) {
  var context = new Axios(defaultConfig);
  // bind方法返回一个新的函数,即instance
  // instance接收到的任意参数,被传入到request方法中

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

  // 把Axios.prototype上的方法绑定到context上下文中,并把这些方法拷贝到 instance 上
  // 比如:会把 Axios.prototype.request 方法拷贝到 instance.request 中
  utils.extend(instance, Axios.prototype, context);

  // 把Axios实例即context上的属性拷贝到instance上
  // 比如 instance.key = context.key
  utils.extend(instance, context);

  return instance;
}

// 创建被导出的默认实例
var axios = createInstance(defaults);

// 导出Axios类被用户继承使用
axios.Axios = Axios;

module.exports = axios;
module.exports.default = axios;

我们在helpers目录下创建bind.js文件,在该文件中实现 bind 函数 bind函数需要传入两个参数

  • fn 要执行的回调函数
  • thisArg fnthis 上下文被绑定到该对象上
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);
  };
};

我们在 utils.js 中实现extend方法 extend方法接收三个参数

  • a 对象类型,要被扩展的对象
  • b 对象类型,需要把该对象上的属性拷贝到 a 对象上
  • thisArg 可选参数,如果存在,把 b 对象上的方法的 this 上下文绑定到该参数
var bind = require("./helpers/bind");

function extend(a, b, thisArg) {
  // 把b参数的属性拷贝到a参数上
  forEach(b, function assignValue(val, key) {
    // thisArg存在(即上下文存在),val为函数,我们把val的上下文绑定到thisArg
    if (thisArg && typeof val === "function") {
      a[key] = bind(val, thisArg);
    } else {
      // thisArg不存在,val可以是任意类型
      a[key] = val;
    }
  });
  return a;
}

module.exports = {
  isArray,
  forEach: forEach,
  trim: trim,
  extend: extend,
};