axios(七)-- 派发请求 dispatchRequest

1、关键点

dispatchRequest中主要做了两件事,
先通过transformData对请求数据进行处理,然后定义适配器adapter并执行,
通过 .then 方法 对adapter(适配器)
resolve 出的响应数据进行处理(transformData)并返回 response,
失败返回一个状态为rejected`的 Promise 对象。
到此,当用户调用 axios()时,可以链式调用 Promise 的 .then() 和 .catch() 来处理业务逻辑了。

2、使用

生成promise链:
let chain = [请求拦截x, ..., 请求拦截2,请求拦截1,  dispatchRequest, undefined,  响应拦截1,响应拦截2, ...响应拦截x]

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

3、源码

lib/core/dispatchRequest.js
// 1、adapter:适配器,包含浏览器端 xhr 和 node 端的 http
let transformData = require('./transformData')
var defaults = require('../../defaults');

module.exports = function dispatchRequest(config) {
	// 	config 是所有请求拦截后的config(因为config可能在拦截时被改动)
    // ...transformData 转换请求数据类型

    // 适配器,可自定义,没有的用默认的
    const adapter = config.adapter || defaults.adapter    

     // 通过适配器处理 config 配置,返回服务端响应数据 response

    return adapter(config).then(function onAdapterResolution(response) {
        // ...转换响应数据
        return response
    
    }, function onAdapterRejection(reason) {
        //...
        return Promise.reject(reason)
    })
}
axios.js
Axios.prototype.request = function request(config) {
    // 为了支持 request(url, {...}), request({url, ...})
    // 方式二:axios('https://xxxx') ,判断参数字符串,则赋值给 config.url
    if (typeof config === 'string') {
      config = arguments[1] || {};
      config.url = arguments[0];
    } else {
      // 方式一:axios({}) ,参数为对象,则直接赋值给 config
      config = config || {};
    }

    // 配置优先级: 调用方法的配置 > 实例化axios的配置 > 默认配置
    // 举个例子,类似:axios.get(url, {}) > axios.create(url, {}) > 内部默认设置
    config = mergeConfig(this.defaults, config);
    // 生成请求拦截队列
    var requestInterceptorChain = [];
    this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
        requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
    });

    // 生成响应拦截队列
    var responseInterceptorChain = [];
    this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
        responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
    });

    /*
    创建用于保存请求/响应拦截函数的数组
    数组的中间放发送请求的函数
    数组的左边放请求拦截器函数(成功/失败)
    数组的右边放响应拦截器函数
    undefined为啥? -->  因为拦截器是成对存在的,所以此处用undefined占位,后续在promise链中可以同前面的一对一对拿出移除
    */

    // 编排整个请求的任务队列
    // 派发请求 dispatchRequest 看下篇
    var chain = [dispatchRequest, undefined];  

    // 为什么unshift要用Array.prototype.unshift.apply??
    Array.prototype.unshift.apply(chain, requestInterceptorChain);

    chain.concat(responseInterceptorChain);

    var promise;
    // 传入配置
    promise = Promise.resolve(config);
    // 形成 promise 链条调用
    // 循环 chain ,不断从 chain 中取出设置的任务,通过 Promise 调用链执行 , 一对一对拿出,一个成功一个失败处理
    while (chain.length) {
      promise = promise.then(chain.shift(), chain.shift());
    }
    // ...
    return promise;
  };
默认的defaults
import utils from './utils'

var defaults = {
    // ...
    // 请求超时时间,默认不超时
    timeout: 0,
    // ...转换请求数据
    // ...转换响应数据
    // ...判断响应状态码的合法性: [200, 299]
    
    adapter: getDefaultAdapter()
}

function getDefaultAdapter () {
  var adapter;

  // 判断当前环境,然后去请求
  if (typeof XMLHttpRequest !== 'undefined') {
    // 浏览器
    adapter = require('./adapters/xhr')
  } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
    // NODE环境,使用http模块
    adapter = require('./adapters/http')
  }

  return adapter
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值