Handwritten axios source code series four: interceptor interceptor

Insert image description here

In the first chapter of this seriesHandwritten axios source code series one: axios core knowledge points some basics of interceptors have been introduced Knowledge, it can be seen that interceptors are divided into:

  • Request interceptor: axios.interceptors.request
  • Response interceptor: axios.interceptors.response

Use the use method to add interceptors, and you can add multiple interceptors. The use method receives two functions as parameters:

  1. fulfilled: the first successful callback passed to promise.then()
  2. rejected: the second failed callback passed to promise.then()

use is used as follows:

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

1. Interceptor interceptor

1. Create the InterceptorManager.js file

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

2. Instantiate the InterceptorManager class in Axios

Before sending a request, the request interceptor needs to be processed, and the response interceptor needs to be processed after the response, and finally the processed response data is returned; therefore, the processing logic of the interceptor is placed in the Axios.prototype.request method.

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;
}

If there are 2 request interceptors and 2 response interceptors, the overall interceptor adding process is as follows:

Insert image description here
The execution chain starts from array index 0, so execute 请求拦截器2 first, then 请求拦截器1, and then dispatchRequestSend a request, execute 响应拦截器1 after request response, 响应拦截器2, and finally return response.

3. Summary

The logic here of the interceptor is actually that the interceptor is added to the array in different ways, so the results are also different. If you understand how unshift and push add data to the array, you will also understand the execution method of the interceptor. When the execution chain is executed later, using shift to get data from the chain will change the length of the chain. Understanding these points will not trouble you. so easy.

Another point is that when declaring the execution chain chain, there is a undefined placeholder. The reason is that when the promise.then(chain.shift(), chain.shift()) code is executed, a pair of callback functions are taken out from the chain each time, one succeeds and the other fails, and placed in the corresponding position for execution. If there is no undefined placeholder, when the dispatchRequest callback function is fetched, the next fetched callback function is the 响应成功1 callback function and is placed in < The location of the failed callback in /span> placeholder is used here. then resulted in an error in the response. In order to ensure the correct operation of the program, the undefined

Guess you like

Origin blog.csdn.net/ThisEqualThis/article/details/130320824