手写axios源码系列四:interceptor拦截器

在这里插入图片描述

在本系列的第一篇章节 手写axios源码系列一:axios核心知识点 中已经介绍过一些拦截器的基础知识,可知拦截器分为:

  • 请求拦截器:axios.interceptors.request
  • 响应拦截器:axios.interceptors.response

使用 use 方法添加拦截器,并且可以添加多个拦截器。use 方法接收两个函数为参数:

  1. fulfilled:传递给 promise.then() 的第一个成功的回调
  2. rejected:传递给 promise.then() 的第二个失败的回调

use 使用方式如下:

  • axios.interceptors.request.use(fulfilled, rejected)
  • axios.interceptors.response.use(fulfilled, rejected)

一、拦截器 interceptor

1、创建 InterceptorManager.js 文件

export default class InterceptorManager {
	constructor(){
		// 因为拦截器可以添加多个,所以用数组保存
		this.handlers = [];
	},
	// 原型对象的 use 方法
	use(fulfilled, rejected){
		this.handlers.push({ fulfilled, rejected })
	}
}

2、Axios 中实例化 InterceptorManager 类

在发送请求前,需要处理请求拦截器,而响应之后需要处理响应拦截器,最后再返回处理过后的响应数据;所以拦截器的处理逻辑放在 Axios.prototype.request 方法中。

import InterceptorManager from "./InterceptorManager.js";

export default class Axios {
	constructor(config){
		this.defaults = config;
		this.interceptors = {
			request: new InterceptorManager(),  // 实例化请求拦截器
			response: new InterceptorManager()  // 实例化响应拦截器
		}
	}
	request(configOrUrl, config){
		if(typeof configOrUrl === "string"){
			config.url = configOrUrl
		} else {
			config = {
				...configOrUrl,
				...config
			}
		}
		// 将 config包装为一个成功状态的 promise对象
		let promise = Promise.resolve(config);
		// 创建执行链,这里调用 dispatchRequest方法以发送请求,undefined起到一个占位符的作用
		const chain = [dispatchRequest, undefined];
		/** 拦截器的处理逻辑 */
		// 将请求拦截器添加到 chain的头部
		this.interceptors.request.handlers.forEach(interceptor => {
			chain.unshift(interceptor.fulfilled, interceptor.rejected)
		});
		// 将响应请求器添加到 chain的尾部
		this.interceptors.response.handlers.forEach(interceptor => {
			chain.push(interceptor.fulfilled, interceptor.rejected)
		});
		// 执行所有的拦截器(一个成功,一个失败)
		while(chain.length){
			promise = promise.then(chain.shift(), chain.shift());
		}
		// 发送请求后返回的是一个 promise对象
		return promise;
}

如果有2个请求拦截器,2个响应拦截器,则拦截器整体添加流程如下图:

在这里插入图片描述
执行链 chain 执行时是从数组索引0开始执行的,所以先执行 请求拦截器2,再执行请求拦截器1,然后执行 dispatchRequest发送请求,请求响应后执行 响应拦截器1响应拦截器2,最后返回 response

3、总结

拦截器这里的逻辑其实就是将拦截器添加到数组的方式不同,所以产生的结果也不同,明白 unshift 与 push 将数据添加到数组的方式,也就明白拦截器的执行方式了。后面执行链执行时,使用 shift 从 chain 中取数据,会改变 chain 的长度,明白这些点也就难不住你了。so easy。

还有一点,就是声明执行链 chain 时,有一个 undefined 占位符。原因就是 promise.then(chain.shift(), chain.shift()) 代码执行时,每次从 chain 中取出成对的回调函数,一个成功,一个失败,放到相应的位置执行。如果没有 undefined 占位,当取到 dispatchRequest 回调函数时,下一个取的就是 响应成功1 的回调函数放到 then 中失败回调的位置,导致响应出错。这里为了保证程序的正确运行,所以使用了 undefined 占位。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值