上一章我们完成了拦截器的代码实现,这一章我们来看看配置化是如何实现的。首先,按照惯例我们来看看axios的文档是怎么说的:

  首先我们可以可以通过axios上的defaults属性来配置api。

  我们可以自己创建一个axios实例,传入对应的可配置参数,然后还可以通过defaults来修改。其实就是后写的配置,会覆盖之前的配置。那么接下来我们就来看代码吧~

  首先,我们在lib根目录下,创建一个defaults文件,在里面写下我们的默认配置:

  目前来说吼,就这么几个配置。 adapter这个默认配置,是用来区分宿主环境的也就是是使用xhr还是http,在咱们这里getDefaultAdapter是这样的:


 import adapterXHR from "./adapters/xhr";

function getDefaultAdapter() {
var adapter;
if (typeof XMLHttpRequest !== "undefined") {
// For browsers use XHR adapter
// adapter = require("./adapters/xhr");
adapter = adapterXHR;
} else if (
typeof process !== "undefined" &&
Object.prototype.toString.call(process) === "[object process]"
) {
// For node use HTTP adapter
// 咱们没有实现服务端的http,所以直接用xhr的
adapter = adapterXHR;
// adapter = require("./adapters/http");
}
return adapter;
}

  很简单哈,就是判断下宿主环境,因为我这里没有实现http部分,所以两个条件判断引入的都是同一个xhr文件。我们再往下看就是默认的transformRequest方法:

  transformRequest: [
function transformRequest(data, headers) {
normalizeHeaderName(headers, "Accept");
normalizeHeaderName(headers, "Content-Type"); if (
utils.isFormData(data) ||
utils.isArrayBuffer(data) ||
utils.isBuffer(data) ||
utils.isStream(data) ||
utils.isFile(data) ||
utils.isBlob(data)
) {
return data;
}
if (utils.isArrayBufferView(data)) {
return data.buffer;
}
if (utils.isURLSearchParams(data)) {
setContentTypeIfUnset(
headers,
"application/x-www-form-urlencoded;charset=utf-8"
);
return data.toString();
} var isObjectPayload = utils.isObject(data);
var contentType = headers && headers["Content-Type"]; if (isObjectPayload && contentType === "multipart/form-data") {
return toFormData(
data,
new ((this.env && this.env.FormData) || FormData)()
);
} else if (isObjectPayload || contentType === "application/json") {
setContentTypeIfUnset(headers, "application/json");
return stringifySafely(data);
} return data;
},
],

  这个transformRequest做的事情比较多,首先就是调用normalizeHeaderName转换两个请求头,这个之前说过,就不多说了,再然后其实就是判断请求body的类型,然后进行一定的请求头适应和转换。transformResponse则比较简单:

  transformResponse: [
function transformResponse(data) {
if (utils.isString(data) && data.length) {
try {
return JSON.parse(data);
} catch (e) {
if (e.name === "SyntaxError") {
throw enhanceError(e, this, "E_JSON_PARSE");
}
throw e;
}
}
return data;
},
],

  这里我去掉了axios原有的transitional参数,因为这个东西可以说几乎用不太到这么细,有兴趣的话大家可以自己去看,如果你一步一步跟到了这里,那么看懂这个参数的应用肯定不在话下。

再然后就是timeout、headers和validateStatus:

  timeout: 0,

  validateStatus: function validateStatus(status) {
return status >= 200 && status < 300;
}, headers: {
common: {
Accept: "application/json, text/plain, */*",
},
},

  timeout和headers不说了,validateStatus实际上就是promise走reject的条件。OK,最后我们还要给defaults的headers根据不同的方法,加一下请求头字段:

utils.forEach(["delete", "get", "head"], function forEachMethodNoData(method) {
defaults.headers[method] = {};
}); utils.forEach(["post", "put", "patch"], function forEachMethodWithData(method) {
defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);
});

  很简单,不多说。完整的代码就在这里,大家可以去看。下面我们就要来看下如何把defaults配置融合进我们的请求中去。首先,我们要找到创建axios的源头的类,也就是Axios类,我们加一点代码:

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

  多了个this.defaults,没错,我们会在创建实例的时候,传入我们上面编写好的defaults,那么我们就去axios.js里面,修改下代码吧:

var axios = createInstance(defaults);

  然后,我们给createInstance方法加一点东西:

instance.create = function create(instanceConfig) {
return createInstance(mergeConfig(defaultConfig, instanceConfig));
};

  也就是我们给生成的Axios实例instance提供一个创建实例的方法create。OK,到了这里哈,我们就可以使用这个defaults配置了,但是我们要去哪用呢?没错!就是Axios的prototype上挂载的request方法里。到目前为止,咱们稍微的小小的回顾下:首先我创建了defaults默认配置 ---> 然后我在Axios类里接收配置 ---> 最后,我在创建axios实例的时候把默认配置传入到Axios类里。那么我们继续,在request方法内,我们需要把创建实例时默认配置和axios实例使用时传入的配置合并一下,注意!我们之前所说的所有的“配置”都是指默认配置,默认配置是在创建实例的时候传递给Axios类使用的。

  var context = new Axios(defaultConfig);

  我们合并的配置是合并的默认配置和手动配置,手动配置指的是传递给axios实例的配置:

axios({
url: "/c6/post",
method: "post",
data: qs.stringify({
a: 1,
}),
headers: {
test: "321",
},
}).then((res) => {
console.log(res.data);
});

  比如这个axios里传的这个对象。我们言归正传,合并下配置:

  config = mergeConfig(this.defaults, config);

  就可以了。这个mergeConfig,之前有说过,不多说了吼。到了现在还没完,我们还有个核心的地方,就是adapter,也就是说,我们要在哪使用这个adapter,怎么使用。之前的dispatchRequest很简单,但是这里我们需要多做一些额外的处理:

import defaults from "../defaults";
import utils from "../utils";
import transformData from "./transformData"; /**
* Dispatch a request to the server using the configured adapter.
*
* @param {object} config The config that is to be used for the request
* @returns {Promise} The Promise to be fulfilled
*/
export default function dispatchRequest(config) {
// Ensure headers exist
config.headers = config.headers || {}; // Transform request data
config.data = transformData.call(
config,
config.data,
config.headers,
config.transformRequest
); // Flatten 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; return adapter(config).then(
function onAdapterResolution(response) {
// Transform response data
response.data = transformData.call(
config,
response.data,
response.headers,
config.transformResponse
); return response;
},
function onAdapterRejection(reason) {
return Promise.reject(reason);
}
);
}

  首先哈,我们获取一下config的headers,然后转换一下config.data,再然后,还记不记得,defaults里的headers是一个二维深度的对象,那么我们需要把它降维,最后我们获取adapter,返回这个adapter的promise即可。到了这里,我粗略的带大家过完了配置化的整条线。其中我略过了一些不常用的源码,也有一部分工具方法没有深入的去讲,那些我个人觉得大家可以自己去看,再读文章的时候,一定要对比着源码来思考,不然的话,可能不太容易理解我说的是啥。

  这章到这里就完事啦。下一章我们去实现axios的取消功能。

一比一还原axios源码(六)—— 配置化的更多相关文章

  1. 一比一还原axios源码(零)—— 概要

    从vue2版本开始,vue-resource就不再被vue所维护和支持,官方也推荐使用axios,所以,从我使用axios至今,差不多有四五年了,这四五年的时间只能算是熟练应用,很多内部的实现和原理不 ...

  2. 一比一还原axios源码(四)—— Axios类

    axios源码的分析,到目前为止,算上第0章已经四章了,但是实际上,还都没有进入axios真正的主线,我们来简单回顾下.最开始我们构建了get请求,写了重要的buildURL方法,然后我们处理请求体请 ...

  3. 一比一还原axios源码(一)—— 发起第一个请求

    上一篇文章,我们简单介绍了XMLHttpRequest及其他可以发起AJAX请求的API,那部分大家有兴趣可以自己去扩展学习.另外,简单介绍了怎么去读以及我会怎么写这个系列的文章,那么下面就开始真正的 ...

  4. 一比一还原axios源码(三)—— 错误处理

    前面的章节我们已经可以正确的处理正确的请求,并且通过处理header.body,以及加入了promise,让我们的代码更像axios了.这一章我们一起来处理ajax请求中的错误. 一.错误处理 首先我 ...

  5. 一比一还原axios源码(八)—— 其他功能

    到此,我们完成了axios的绝大部分的功能,接下来我们来补全一下其他的小功能. 一.withCredentials  这个参数可以可以表明是否是一个跨域的请求.那这个的使用场景是啥呢?就是我们在同域的 ...

  6. 一比一还原axios源码(二)—— 请求响应处理

    上一章,我们开发了一些简单的代码,这部分代码最最核心的一个方法就是buildURL,应对了把对象处理成query参数的方方面面.虽然我们现在可以发起简单的请求了,但是第一,我们无法接收到服务器的响应, ...

  7. 一比一还原axios源码(五)—— 拦截器

    上一篇,我们扩展了Axios,构建了一个Axios类,然后通过这个Axios工厂类,创建真正的axios实例.那么今天,我们来实现下Axios的拦截器也就是interceptors.我们来简单看下Ax ...

  8. RocketMQ源码 — 六、 RocketMQ高可用(1)

    高可用究竟指的是什么?请参考:关于高可用的系统 RocketMQ做了以下的事情来保证系统的高可用 多master部署,防止单点故障 消息冗余(主从结构),防止消息丢失 故障恢复(本篇暂不讨论) 那么问 ...

  9. Axios源码深度剖析 - 替代$.ajax,成为xhr的新霸主

    前戏 在正式开始axios讲解前,让我们先想想,如何对现有的$.ajax进行简单的封装,就可以直接使用原声Promise了? let axios = function(config){ return ...

随机推荐

  1. mysql表查询、多表查询(增强查询的使用)子查询、合并查询,外连接,mysql5种约束,自增长

    一.查询加强 1.在mysql中,日期类型可以直接比较,需要注意格式 2.%:表示0到多个字符, _:表示单个字符 exp:显示第二个字符为大写O的所有员工的姓名和工资 select  name fr ...

  2. 【前端开发日记 】VSCODE被初始化之后重新设置的这些事

    不知到什么插件的原因,导致我的vscode编辑器,在输入比如div的时候按tab不会识别成html标签,在设置了推荐词之后还是不好使,于是初始化了自己的编辑器设置 ,导致所有的插件和个性化设置都不见了 ...

  3. java中最简单的计算执行时长的方式

    日常在做一些性能测试的时候会通过执行时间来判断执行时长,java中最简单的方式如下: //开始时间 long startL= new Date().getTime(); //这里需要导入 java.u ...

  4. Solution -「ARC 124E」Pass to Next

    \(\mathcal{Description}\)   Link.   有 \(n\) 个人站成一个环,初始时第 \(i\) 个人手里有 \(a_i\) 个球.第 \(i\) 个人可以将自己手中任意数 ...

  5. Solution -「ARC 101D」「AT4353」Robots and Exits

    \(\mathcal{Description}\)   Link.   有 \(n\) 个小球,坐标为 \(x_{1..n}\):还有 \(m\) 个洞,坐标为 \(y_{1..m}\),保证上述坐标 ...

  6. Solution -「NOI 2008」「洛谷 P3980」志愿者招募

    \(\mathcal{Description}\)   Link.   一项持续 \(n\) 天的任务,第 \(i\) 天需要至少 \(a_i\) 人工作.还有 \(m\) 种雇佣方式,第 \(i\) ...

  7. Note -「单位根反演」学习笔记

    \(\mathcal{Preface}\)   单位根反演,顾名思义就是用单位根变换一类式子的形式.有关单位根的基本概念可见我的这篇博客. \(\mathcal{Formula}\)   单位根反演的 ...

  8. 排查log4j不输出日志到文件的问题

    问题描述 项目使用Spring Boot框架,在pom文件中添加了如下配置: <dependency> <groupId>org.slf4j</groupId> & ...

  9. 【程序员的实用工具推荐】 Mac 效率神器 Alfred

    Alfred 是一款功能非常强大,能有效提升 Mac 电脑使用效率的神器.可以说有了 Alfred 你就基本上可以脱离鼠标实现各种操作.相比 Mac 自带的聚焦搜索,完全可以称得上拥有碾压性的优势. ...

  10. HDFS免重启挂载新磁盘

    背景 在生产环境中,集群节点磁盘大小不同,其使用率也会不同,HDFS虽有均衡策略,但也会有数据不平衡的情况,有些节点磁盘就会被打满,然后这个节点就不健康了(Unhealthy Nodes),Yarn的 ...