axios - 8 - Axios

console.info

该系类文章旨在研究 axios 的实现 。在研究源码的基础上,去理解 axios 是如何实现 ajax 请求并更好的去使用这个库。

简介

对应文件为 lib/core/Axios.js

根据前面的相关博文,该有的方法都有了,该有的配置也都已经规定好,在 Axios 这个类中,我们只需要绑定配置然后去调用相关的方法就可以了。

代码分析

类下的属性

function Axios(instanceConfig) {
    this.defaults = instanceConfig;
    this.interceptors = {
        request: new InterceptorManager(),
        response: new InterceptorManager()
    };
}

绑定初始化值,和对 request response 的注入。
当我们需要在请求开始前对请求头以及数据内容做手脚的话,就可以调用,axios.interceptors.use,如下所示:

var axios = new Axios({/*一些默认的请求数据,具体内容见 config 一章*/})
axios.interceptors.request.use(succssCall,failCall);
function succssCall(config){
    // 修改 header data 等等
}
function failCall(config){
    // ...
}

类下方法

  • request 发送请求
Axios.prototype.request = function request(config) {
    // 允许 axios('example/url'[, config]) 方式进行调用,即参数一为请求地址
    if (typeof config === 'string') {
        config = utils.merge({
            url: arguments[0]
        }, arguments[1]);
    }

    // 合并请求需要的 config 由于后者覆盖前者,所以重要的放后面
    config = utils.merge(defaults, this.defaults, {method: 'get'}, config);

    // 支持 baseURL 写法
    if (config.baseURL && !isAbsoluteURL(config.url)) {
        config.url = combineURLs(config.baseURL, config.url);
    }

    // chain 为一个数组连,刚开始中间只放了两项:发送请求函数、undefined。
    // 至于为什么要有这个 undefined 看下去就懂了。
    var chain = [dispatchRequest, undefined];
    // 初始化一个 promise 带上我们刚合并好的 config
    var promise = Promise.resolve(config);

    // 将 request 的注入添加到 chain 的头部,也就是请求发送前
    this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
        chain.unshift(interceptor.fulfilled, interceptor.rejected);
    });

    // 将 response 的注入添加到 chain 的尾部,也就是请求发送后
    this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
        chain.push(interceptor.fulfilled, interceptor.rejected);
    });

    // 然后一次从 chain 中取出两项,放到 promise 中供 promise 不断的 then 方法调用
    // 这也是为什么初始化 chain 时需要一个 undefined
    while (chain.length) {
        promise = promise.then(chain.shift(), chain.shift());
    }

    return promise;
};
  • [method] 一些快捷操作
// 对与 'delete', 'get', 'head' 这些不需要请求体的请求,添加如
// axios.get(url, config)的方法
// 但个人感觉在加一个 params 会不会好一点
utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {
    /*eslint func-names:0*/
    Axios.prototype[method] = function (url, config) {
        return this.request(utils.merge(config || {}, {
            method: method,
            url: url
        }));
    };
});

// 对与 'post', 'put', 'patch' 这些需要请求体的请求,添加如
// axios.post(url, data, config)的方法
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
        }));
    };
});

总结

实例化 Axios 之后,直接调用 request 就可以发送请求了。