axios 中的 XHR 模块相对简单,它是对?`XMLHTTPRequest`?对象的封装,这里我就不再解释了。有兴趣的同学,可以自己阅读源源码看看,源码位于?`adapters/xhr.js`?文件中。
### 拦截器模块
现在让我们看看 axios 是如何处理,请求和响应拦截器函数的。这就涉及到了 axios 中的统一接口 ——`request`?函数。
Axios.prototype.request = function request(config) {
var chain = [dispatchRequest, undefined];
var promise = Promise.resolve(config);
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
chain.unshift(interceptor.fulfilled, interceptor.rejected);
});
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
chain.push(interceptor.fulfilled, interceptor.rejected);
});
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
};
这个函数是 axios 发送请求的接口。因为函数实现代码相当长,这里我会简单地讨论相关设计思想:
1. `chain`?是一个执行队列。队列的初始值是一个携带配置(`config`)参数的 Promise 对象。
2. 在执行队列中,初始函数?`dispatchRequest`?用来发送请求,为了与?`dispatchRequest`对应,我们添加了一个?`undefined`。添加?`undefined`?的原因是需要给 Promise 提供成功和失败的回调函数,从下面代码里的?`promise = promise.then(chain.shift(), chain.shift());`?我们就能看出来。因此,函数?`dispatchRequest`?和?`undefiend`?可以看成是一对函数。
3. 在执行队列?`chain`?中,发送请求的?`dispatchReqeust`?函数处于中间位置。它前面是请求拦截器,使用?`unshift`?方法插入;它后面是响应拦截器,使用?`push`?方法插入,在?`dispatchRequest`?之后。需要注意的是,这些函数都是成对的,也就是一次会插入两个。
浏览上面的?`request`?函数代码,我们大致知道了怎样使用拦截器。下一步,来看看怎样撤销一个 HTTP 请求。
### 撤销请求模块
与撤销请求相关的模块位于?`Cancel/`?文件夹下,现在我们来看下相关核心代码。
首先,我们来看下基础?`Cancel`?类。它是一个用来记录撤销状态的类,具体代码如下:
function Cancel(message) {
this.message = message;
}
Cancel.prototype.toString = function toString() {
return ‘Cancel’ + (this.message ? ': ’ + this.message : ‘’);
};
Cancel.prototype.CANCEL = true;
使用?`CancelToken`?类时,需要向它传递一个 Promise 方法,用来实现 HTTP 请求的撤销,具体代码如下:
function CancelToken(executor) {
if (typeof executor !== 'function') {
throw new TypeError('executor must be a function.');
}
var resolvePromise;
this.promise = new Promise(function promiseExecutor(resolve) {
resolvePromise = resolve;
});
var token = this;
executor(function cancel(message) {
if (token.reason) {
return;
}
token.reason = new Cancel(message);
resolvePromise(token.reason);
});
}
CancelToken.source = function source() {
var cancel;
var token = new CancelToken(function executor(c) {
cancel = c;
});
return {
token: token,
cancel: cancel
};
};
`adapters/xhr.js`?文件中,撤销请求的地方是这样写的:
if (config.cancelToken) {
config.cancelToken.promise.then(function onCanceled(cancel) {
if (!request) {
return;
}
request.abort();
reject(cancel);
request = null;
});
}
通过上面的撤销 ?HTTP请求的例子,让我们简要地讨论一下相关的实现逻辑:
1. 在需要撤销的请求中,调用?`CancelToken`?类的?`source`?方法类进行初始化,会得到一个包含?`CancelToken`?类实例 A?和?`cancel`?方法的对象。
2. 当 source 方法正在返回实例 A 的时候,一个处于 pending 状态的?`promise`?对象初始化完成。在将实例 A 传递给 axios 之后,`promise`?就可以作为撤销请求的触发器使用了。
3. 当调用通过?`source`?方法返回的?`cancel`?方法后,实例 A 中?`promise`?状态从 pending 变成 fulfilled,然后立即触发?`then`?回调函数。于是 axios 的撤销方法——`request.abort()`?被触发了。
**axios 这样设计的好处是什么?**
---------------------
### 发送请求函数的处理逻辑
如前几章所述,axios 不将用来发送请求的?`dispatchRequest`?函数看做一个特殊函数。实际上,`dispatchRequest`?会被放在队列的中间位置,以便保证队列处理的一致性和代码的可读性。
### 适配器的处理逻辑
在适配器的处理逻辑上,`http`?和?`xhr`?模块(一个是在 Node.js 中用来发送请求的,一个是在浏览器里用来发送请求的)并没有在?`dispatchRequest`?函数中使用,而是各自作为单独的模块,默认通过?`defaults.js`?文件中的配置方法引入的。因此,它不仅确保了两个模块之间的低耦合,而且还为将来的用户提供了定制请求发送模块的空间。
### 撤销 HTTP 请求的逻辑
在撤销 HTTP 请求的逻辑中,axios 设计使用 Promise 来作为触发器,将?`resolve`?函数暴露在外面,并在回调函数里使用。它不仅确保了内部逻辑的一致性,而且还确保了在需要撤销请求时,不需要直接更改相关类的样例数据,以避免在很大程度上入侵其他模块。
**总结**
------
### 最后
中年危机是真实存在的,即便有技术傍身,还是难免对自己的生存能力产生质疑和焦虑,这些年职业发展,一直在寻求消除焦虑的依靠。
* 技术要深入到什么程度?
* 做久了技术总要转型管理?
* 我能做什么,我想做什么?
* **一技之长,就是深耕你的专业技能,你的专业技术。**(重点)
* 独立做事,当你的一技之长达到一定深度的时候,需要开始思考如何独立做事。(创业)
* 拥有事业,选择一份使命,带领团队实现它。(创业)
**一技之长分五个层次**
* 栈内技术 - 是指你的前端专业领域技术
* 栈外技术 - 是指栈内技术的上下游,领域外的相关专业知识
* 工程经验 - 是建设专业技术体系的“解决方案”
* 带人做事 - 是对团队协作能力的要求
* 业界发声 - 工作经验总结对外分享,与他人交流
> 永远不要放弃一技之长,它值得你长期`信仰持有`。
**[CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](
)**
> 主要内容包括html,css,html5,css3,JavaScript,正则表达式,函数,BOM,DOM,jQuery,AJAX,vue 等等。
![](https://img-blog.csdnimg.cn/img_convert/44bc3d1e2743a7cf1e94e28026aedf8d.png)
> **本文已被[CodeChina开源项目:【一线大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://codechina.csdn.net/m0_60958482/web-p7)收录,自学编程路线及系列技术文章等资源持续更新中...**
|