一比一还原axios源码(六)—— 配置化
上一章我们完成了拦截器的代码实现,这一章我们来看看配置化是如何实现的。首先,按照惯例我们来看看axios的文档是怎么说的:
首先我们可以可以通过axios上的defaults属性来配置api。
我们可以自己创建一个axios实例,传入对应的可配置参数,然后还可以通过defaults来修改。其实就是后写的配置,会覆盖之前的配置。那么接下来我们就来看代码吧~
首先,我们在lib根目录下,创建一个defaults文件,在里面写下我们的默认配置:
目前来说吼,就这么几个配置。 adapter这个默认配置,是用来区分宿主环境的也就是是使用xhr还是http,在咱们这里getDefaultAdapter是这样的:
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源码(六)—— 配置化的更多相关文章
- 一比一还原axios源码(零)—— 概要
从vue2版本开始,vue-resource就不再被vue所维护和支持,官方也推荐使用axios,所以,从我使用axios至今,差不多有四五年了,这四五年的时间只能算是熟练应用,很多内部的实现和原理不 ...
- 一比一还原axios源码(四)—— Axios类
axios源码的分析,到目前为止,算上第0章已经四章了,但是实际上,还都没有进入axios真正的主线,我们来简单回顾下.最开始我们构建了get请求,写了重要的buildURL方法,然后我们处理请求体请 ...
- 一比一还原axios源码(一)—— 发起第一个请求
上一篇文章,我们简单介绍了XMLHttpRequest及其他可以发起AJAX请求的API,那部分大家有兴趣可以自己去扩展学习.另外,简单介绍了怎么去读以及我会怎么写这个系列的文章,那么下面就开始真正的 ...
- 一比一还原axios源码(三)—— 错误处理
前面的章节我们已经可以正确的处理正确的请求,并且通过处理header.body,以及加入了promise,让我们的代码更像axios了.这一章我们一起来处理ajax请求中的错误. 一.错误处理 首先我 ...
- 一比一还原axios源码(八)—— 其他功能
到此,我们完成了axios的绝大部分的功能,接下来我们来补全一下其他的小功能. 一.withCredentials 这个参数可以可以表明是否是一个跨域的请求.那这个的使用场景是啥呢?就是我们在同域的 ...
- 一比一还原axios源码(二)—— 请求响应处理
上一章,我们开发了一些简单的代码,这部分代码最最核心的一个方法就是buildURL,应对了把对象处理成query参数的方方面面.虽然我们现在可以发起简单的请求了,但是第一,我们无法接收到服务器的响应, ...
- 一比一还原axios源码(五)—— 拦截器
上一篇,我们扩展了Axios,构建了一个Axios类,然后通过这个Axios工厂类,创建真正的axios实例.那么今天,我们来实现下Axios的拦截器也就是interceptors.我们来简单看下Ax ...
- RocketMQ源码 — 六、 RocketMQ高可用(1)
高可用究竟指的是什么?请参考:关于高可用的系统 RocketMQ做了以下的事情来保证系统的高可用 多master部署,防止单点故障 消息冗余(主从结构),防止消息丢失 故障恢复(本篇暂不讨论) 那么问 ...
- Axios源码深度剖析 - 替代$.ajax,成为xhr的新霸主
前戏 在正式开始axios讲解前,让我们先想想,如何对现有的$.ajax进行简单的封装,就可以直接使用原声Promise了? let axios = function(config){ return ...
随机推荐
- 还在做廉价的劳动力?部署PXE实现Kickstart无人值守安装
搭建PXE实现Kickstart无人值守安装 1.搭建PXE远程安装服务器 2.实现kicstart无人值守安装 1.PXE介绍及搭载: PXE是有Intel公司开发的网络引导技术,工作在Client ...
- pytest(4)-测试用例执行顺序
前言 上一篇文章我们讲了在pytest中测试用例的命名规则,那么在pytest中又是以怎样的顺序执行测试用例的呢? 在unittest框架中,默认按照ACSII码的顺序加载测试用例并执行,顺序为:09 ...
- BumbleBee: 如丝般顺滑构建、交付和运行 eBPF 程序
本文地址:https://www.ebpf.top/post/bumblebee 1. 前言 不久前,Solo.io 公司在官网博客宣布了开源了一个名称为 BumbleBee 的新项目.该项目专注于简 ...
- Windows安装PostgreSQL解压版
PostgreSQL下载地址:https://www.enterprisedb.com/downloads/postgres-postgresql-downloads windows版,务必装在C盘! ...
- 在win10上安装face_recognition(人脸识别)
github上有个项目face_recognition,是用于人脸识别的 主要是window上安装这个项目会繁琐些,linux上据项目文档上介绍是妥妥的. 项目地址: https://github. ...
- 前端提交数据到node的N种方式
写在前面 本篇介绍了前端提交数据给node的几种处理方式,从最基本的get和post请求,到图片上传,再到分块上传,由浅入深. GET请求 经典的get提交数据,参数通过URL传递给node,node ...
- macbook安装scala、hadoop、saprk环境
一.scala安装 1. 安装jdk 有mac专用的jdk安装包,这里下载安装jdk1.8 2. 安装scala 2.1下载scala 2.2解压到指定目录 tar -zxvf /Users/lode ...
- sql server通过T-SQL导出Excel到磁盘
ALTER PROCEDURE [dbo].[pro_ImportExcelByTime] AS BEGIN --第一步,开启高级功能 EXEC sp_configure 'show advanced ...
- [Java]Java中的自动包装
来源:https://www.cnblogs.com/cheapcrook/archive/2012/04/25/2470478.html 自动拆装箱(AutoBoxing) 是JDK1.5中新增加的 ...
- centos7云服务器安装nginx记录
nginx作为一个web和反向服务器,应用广泛,尤其适合学习c/c++的人进行使用学习,今天就对这个我听了很多的nginx进行了一次安装配置,主要是针对菜鸟教程中的安装引导进行的个人试验.主要的关注点 ...