axios源码解析-dispatchRequest

axios源码解析-dispatchRequest

dispatchRequest.js是整个axios中处理请求最核心的方法,他包括了验证取消请求,数据转化,Ajax封装(适配器的使用),我们来看一下这一部分的源码

// 检验是否需要取消请求
function throwIfCancellationRequested(config) {
    if (config.cancelToken) {
        config.cancelToken.throwIfRequested();
    }
}

首先,axios定义了一个方法,通过检查config中的一个配置来决定是否取消请求。之后,这个js文件导出了dispatchRequest这个函数,这个函数首先调用了检验取消请求的
函数,然后,调用了transformData这个方法,在发送前对数据进行处理

module.exports = function dispatchRequest(config) {
    // 检验是否需要取消请求
    throwIfCancellationRequested(config);

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

    // Transform request data
    // 传入数据和请求头,并用transfromData进行修改
    // `transformRequest` 允许在向服务器发送前,修改请求数据
    // 它只能用与 'PUT', 'POST' 和 'PATCH' 这几个请求方法
    // 数组中最后一个函数必须返回一个字符串, 一个Buffer实例,ArrayBuffer,FormData,或 Stream
    // 你可以修改请求头。
    //   transformRequest: [function (data, headers) {
    //     // 对发送的 data 进行任意转换处理

    //     return data;
    //   }],
    // 这里的data是在发送请求前最终处理完成后返回的data
    // 调用transfrom处理请求前的参数
    config.data = transformData.call(
        config,
        config.data,
        config.headers,
        config.transformRequest //这一项作为回调函数
    );

这个transfromData的函数究竟做就什么事呢,我们来看看transfromData这个函数究竟做了什么事

// 解析并在请求前处理数据
module.exports = function transformData(data, headers, fns) {
    //这里的fns是一个函数数组,在axios自定义的foreach中,如果参数是数组,会让每一项都执行回调函数
    var context = this || defaults;
    /*eslint no-param-reassign:0*/
    utils.forEach(fns, function transform(fn) {
        // 这里最终相当于this被绑定在了context上,将data和headers作为参数执行transfrom中的每一个方法,并返回一个data
        data = fn.call(context, data, headers);
    });

    return data;
};

这个函数有一点复杂,各种参数相互传递,看的人有点懵,其实理清各种参数的关系还是很好理解的,这里跟拦截器那部分的处理也很相似,将所有要进行处理的函数放到一个数组里,然后用foreach(这里的foreach是自定义的,跟JS里的foreach相似但不完全一样)进行遍历,对这个函数数组里的每一项绑定this并执行,更新data,最终,这个部分就会执行我们在配置里定义的所有transfromData方法并更新数据data

之后,对请求头进行了一些处理,合并了一些配置,并除去了一些无用属性

  // 处理优先级,用后进来的对象去修改和补充先进来的对象的属性参数
    // 抽出请求头的common和当前请求的methods合并到首层结构
    // 合并修改数据后的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;

我们来看一下defaults.js这部分中对适配器的定义

function getDefaultAdapter() {
    var adapter;
    if (typeof XMLHttpRequest !== 'undefined') {
        // For browsers use XHR adapter
        adapter = require('./adapters/xhr');
    } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
        // For node use HTTP adapter
        adapter = require('./adapters/http');
    }
    return adapter;
}

    adapter: getDefaultAdapter(),

我们可以看到,适配器其实是一个函数,他会判断当前运行环境,如果是浏览器环境,就执行对AJAX的封装部分的函数,如果是node环境,就执行对HTTP进行封装的函数,不论是那个,都一定是一个异步函数,因此,下一步中,直接传入配置并调用then方法,执行请求部分的回调函数,确认是否取消请求,并再次transfromData对返回的响应数据进行处理,这部分跟请求前的数据处理原理是意义的。如果失败的话,同样对能够返回的数据进行处理。这个部分返回的是一个异步函数,用于在执行链的阶段跟拦截器执行相同的链式调用

  return adapter(config).then(function onAdapterResolution(response) {
        // 适配器的成功回调
        throwIfCancellationRequested(config);
        // 处理并返回信息
        // Transform response data
        response.data = transformData.call(
            config,
            response.data,
            response.headers,
            // 对响应的数据进行统一处理
            config.transformResponse
        );

        return response;
    }, function onAdapterRejection(reason) {
        // 适配器的失败回调
        // 如果没有取消请求,继续对数据包数据进行处理
        if (!isCancel(reason)) {
            throwIfCancellationRequested(config);

            // Transform response data
            if (reason && reason.response) {
                // 请求失败也会对响应的data和响应头进行处理
                reason.response.data = transformData.call(
                    config,
                    reason.response.data,
                    reason.response.headers,
                    config.transformResponse
                );
            }
        }

        return Promise.reject(reason);
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
axios是一个基于Promise的HTTP客户端库,可以用于浏览器和Node.js环境中向服务器发送HTTP请求。它是一个功能强大且易于使用的库,可以与Vue.js等前端框架很好地配合使用。 vue-axios是一个适用于Vue.js的插件,它将axios集成到Vue.js中,使我们可以在Vue组件中更方便地使用axios发送HTTP请求。通过使用vue-axios插件,我们可以在Vue实例和Vue组件中直接使用this.$http来代替axios实例来发送请求,简化了我们的代码并提高了开发效率。 虽然我们也可以直接使用axios来发送请求,但使用vue-axios插件更符合Vue整体生态环境的设计原则。直接写原型链的方式可能会显得比较粗暴,并且不太推荐,除非是在底层实现的时候。因此,我们更推荐使用vue-axios插件的方式来结合Vue.js框架使用axios。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [axios和vue-axios](https://blog.csdn.net/qq_43654065/article/details/121288529)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Vue axios和vue-axios的关系及使用区别](https://blog.csdn.net/u014641168/article/details/126096526)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值