axios取消请求原理、拦截器原理

本文详细讲解了axios的拦截器工作原理,包括请求与响应拦截,以及如何手写简单的axios并对比其与原生Ajax的异同。重点阐述了axios的取消请求机制,同时讨论了axios相对于Ajax的优势和区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ajax、axios相关的面试题

面试题

  • axios的优点,axios和ajax的区别
  • 原生实现ajax,说一下怎么用ajax发送请求
  • ajax的封装,取消请求,使用ajax封装类似axios可以实现的拦截器功能
  • axios 的拦截器原理
  • 那axios是怎样取消请求的

概述

axios是什么?
基于promise的异步ajax请求库

axios有什么新特点?

  • 支持请求/响应拦截器 ★
  • 支持请求取消
  • .浏览器端(创建ajax请求)/node端(创建一般的HTTP请求)都可以使用
  • 请求/响应数据转换 --> 使用时写的是对象,axios自动转换成了json。接受时axios也自动将json转换为了对象

axios拦截器原理

拦截器的使用

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
  	  // 对请求错误做些什么
    return Promise.reject(error);
  });
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
});

const interceptorId = axios.interceptors.request.use(function () {/*...*/}); 
axios.interceptors.request.eject(interceptorId); 
/*
在axios对象属性中暴露出了一个interceptors这个属性对象,该对象有两个属性分别是request、response,这两个属性存分别对应请求前与请求后我们想做的一些操作,再调用use函数配置了两个函数进去。
*/

拦截器原理: 本质是一个顺序问题 请求拦截器-api请求-响应拦截器

  1. 拦截器中,定义了handlers 数组收集了所有的拦截器方法。
  2. axios使用的是数组的方式完成了链式调用,通过request与response的forEach方法,将请求拦截器插入到chain(请求api)的前面,将响应拦截器插入到chain(请求api)的后面。
  3. 执行时从队头开始执行,所以请求拦截器后设置的先执行,响应拦截器先设置的先执行。
    在这里插入图片描述
var promise = Promise.resolve(config);
  while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift());
  }

axios取消请求的原理

取消请求的使用
1.excutor执行器函数是同步执行的,参数是用于取消当前请求的函数
2.当取消当前请求的函数被调用时,该请求会进入失败的流程,请求失败的error是Cancel对象类型,Cancel里面有message属性

let cancel //保存用于取消请求的函数
axios.get("/user",{
	//new axios.CancelToken时得到一个函数
     cancelToken:new axios.CancelToken(function excutor(c){
	 	cancel = c; //准备发请求时先把取消请求的函数保存起来,后续可以调用来取消当前请求
	}).then(response =>{
        cancel = null; //如果请求完成就不要取消请求了
    },error =>{
		cancel = null; //失败之后也不需要取消了
	})
})

取消请求的原理

  1. new axios.CancelToken时函数内部准备一个promise对象,并将promise的resolve函数保存起来。
  2. 执行外部定义的执行器函数,将取消函数作为参数传递。取消请求函数的作用是执行时将promise指定为成功,值为Cancel对象。
    3.当取消请求函数执行时(将promise修改成成功了),获取之前保存的promise状态,如果成功并且请求还没有执行完成则执行request.abort()中断请求,并调用reject(cancel对象)将发请求的promise状态改为失败。
function CancelToken(excutor){
//...
let resolvePromise;
//为取消请求准备一个promise对象,并保存resolve函数
this.promise = new Promise(function promiseExecutor(resolve){
	resolvePromise = resolve;
})
let token = this; //保存当前CancelToken对象
//执行同步执行器,function cancel为参数,这个参数就取消请求的参数
excutor(function cancel(message){ 
	//....
	//将token的reason指定为一个Cancel对象
	token.reason = new Cancel(message);
	resolvePromise(token.reason); //将取消请求的promise指定为成功,成功的值为reason
})
}

//取消请求部分的代码
if(config.cancelToken){
	config.cancelToken.promise.then(function onCanceled(cancel){
		if(!request)return;
		request.abort();//中断请求
		reject(cancel);
		request = null
	})
}

手写ajax (简单的axios)

  1. 参数是option配置对象,返回promise对象
  2. 利用XHR对象发送ajax请求
    1. 创建xhr对象new XMLHttpRequest()
    2. 初始化xhr连接xhr.open(method,url,true) 默认async:true,参数是请求行
    3. 发送请求xmr.send() 参数为字符串,可以是json对象字符串,也可以是urlencoded格式字符串
    4. xml.onreadystatechange 用于监听请求状态的改变,send是异步的
      readyState 0:初始 1:open()之后 2:send()之后 3:请求中 4:请求完成
  3. 处理结果,返回status、statusText 以及响应数据,数据需要转换为字符串/对象格式
function axios({
	url,
	method='GET',
	params={},
	data={},
}){
	return new Promise(resolve,reject){
    //数据初始化操作
    let query ='' ;
    Object.keys(params).forEach(key => {
        query += `${key}=${params[key]}&` 
    })
    if(query){
      query = query.substring(0,query.length-1);
      url = url + '?' + query;
    }
    method = method.toUpperCase();
    let xhr = new XMLHttpRequest() //创建xhr对象
    xhr.open(url,method); //初始化请求

    //状态监听,send是异步的
    xhr.onreadystatechange = function(){
      if(xhr.readyState !==4) return;
      //请求完成
      let {status,statusText} = xhr;
      if (status>=200&&status<=299){
        const response = {
          data:JSON.parse(xhr.response),
          status,
          statusText,
      }
      resolve(response)
      }else{
        reject(new Error(`request error status is ${status}`))
      }
    }

    switch(method){//发送请求
        case 'GET' || 'DELETE':
          xhr.send();
          break;
        case 'POST' || 'PUT':
          xhr.setRequestHeader("Content-Type","application/json;charset=utf");
          xhr.send(JSON.stringify(data));
    } 
	}
}
XHR对象的常用方法或属性
方法/属性描述
readyState请求的状态 0:初始 1:open()之后 2:send()之后 3:请求中 4:请求完成
onreadystatechange监视回调函数绑定readyState改变的监听 on…当…时执行
open(method,url[,async])初始化一个请求 默认async:true,参数是请求行
send(data)发送请求 参数为字符串,可以是json对象字符串,也可以是urlencoded格式字符串
abort()中断请求 中断的是发出请求,还没结束的请求
<think>好的,用户想了解如何在前端使用Axios实现请求拦截器的教程、示例和用法。首先,我需要整理一下Axios的基本概念和拦截器的作用。Axios是一个基于Promise的HTTP客户端,广泛用于前端项目中。请求拦截器可以在发送请求之前对配置进行处理,比如添加统一的请求头、身份验证Token或者修改请求参数。 接下来,我需要参考用户提供的引用内容。引用[2]提到使用请求拦截器统一携带Token,并简要说明了拦截器的用途。引用[3]详细说明了请求拦截器和响应拦截器的定义和作用,可以从中提取关键步骤。引用[4]则提到Vue中推荐使用Axios,所以可能需要考虑在Vue项目中的配置方式。 然后,我需要确定回答的结构。根据用户的要求,回答需要结构清晰,逐步解决问题。可能需要分步骤讲解,包括安装Axios、创建实例、添加拦截器、示例代码以及处理错误等。同时,要确保所有数学表达式和代码块格式正确,但根据用户问题,这里可能主要涉及代码示例,所以需要特别注意代码的格式和注释。 用户可能需要具体的示例代码,所以应该提供完整的代码片段,比如如何创建Axios实例,如何使用拦截器添加Token,如何处理错误等。同时,要提到最佳实践,比如在Vue中的使用,以及如何结合响应拦截器统一处理错误。 还需要注意引用标识的正确添加。比如在提到添加请求头时,引用[1]中的步骤可能相关,但根据用户提供的引用内容,引用[2]、[3]、[4]更直接相关,所以需要正确标注。 最后,生成相关问题,可能涉及拦截器的其他应用场景、错误处理、与响应拦截器的配合使用,以及如何测试拦截器是否生效。这些问题需要与用户的问题紧密相关,并且能够引导进一步学习。</think>### Axios请求拦截器实现教程 #### 一、Axios拦截器核心原理 Axios拦截器通过Promise链式调用机制,在请求发出前和响应接收后插入处理逻辑。请求拦截器接收`config`对象,可修改请求参数、添加公共头信息或Token认证[^2][^3]。 #### 二、具体实现步骤 1. **安装Axios** ```bash npm install axios ``` 2. **创建Axios实例** ```javascript // src/utils/request.js import axios from 'axios' const service = axios.create({ baseURL: 'https://api.example.com', timeout: 5000 }) ``` 3. **添加请求拦截器** ```javascript service.interceptors.request.use( config => { // 注入Token(示例) const token = localStorage.getItem('ACCESS_TOKEN') if (token) { config.headers.Authorization = `Bearer ${token}` } // 统一添加时间戳 config.params = { ...config.params, _t: Date.now() } return config }, error => { return Promise.reject(error) } ) ``` 4. **响应拦截器配合使用** ```javascript service.interceptors.response.use( response => { // 统一处理响应数据 return response.data }, error => { // 处理401未授权错误 if (error.response.status === 401) { router.push('/login') } return Promise.reject(error) } ) ``` 5. **导出实例** ```javascript export default service ``` #### 三、实际使用示例 ```javascript import request from '@/utils/request' // 发送带拦截器请求 request.get('/user/info') .then(data => console.log(data)) .catch(err => console.error('请求失败:', err)) ``` #### 四、最佳实践建议 1. **环境区分**:通过`process.env.NODE_ENV`动态设置baseURL 2. **安全处理**:在拦截器中过滤敏感参数 3. **性能优化**:添加请求取消功能 4. **类型提示**:为拦截器添加TypeScript类型定义
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值