axios-retry 响应异常

文章讲述了在项目中遇到axios的ECONNABORTED错误,通过引入axios-retry进行重试请求。然而,这导致拦截器被多次触发,影响了数据获取。作者调整了拦截器逻辑并发现了未使用的`window.stop`导致的问题。

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

最近项目中遇到 axios 异步请求异常中断, 错误码为 “ECONNABORTED”
奇怪的是排查前端代码并没有发现有主动调用 abort 取消请求的
由于为何网络请求失败的原因找不到, 但是重试请求就是成功的, 所以计划使用 axios-retry 在网络错误时重新请求

import axiosRetry from 'axios-retry'
import axios from 'axios'

const service = axios.create({
	// .... 各种配置项
})

axiosRetry(service, {
	retries: 1,  // 重新请求次数, 这里由于只是为了解决特殊情况下的网络错误, 所以只重试一次即可
	// 重试条件
	retryCondition: error => {
    	return error.code === 'ECONNABORTED' // 仅这个错误下重试请求
	}
})

使用以上方案后, 解决了网络错误下接口失败的问题, 但是发现在重试请求成功后, js 代码里拿到的结果不对
经过排查, 发现 axios-retry 虽然能重新请求, 但是会基于实际请求次数多次调用 interceptors 拦截器的钩子

拦截器代码

service.interceptors.response.use(
	response => {
		return response.data
	},
	error => {
		ElMessage({
			message: error.message,
			type: 'error',
			duration: 3000
		})
	}
)

拦截器钩子第二次执行时返回的实际上是 response.data.data, 这会导致外部调用者拿不到预期结果 但这是 axios 或 axios-retry 内部的问题, 我们无法解决, 所以只能在钩子里做判断, 如果当前请求已经进入过拦截器处理, 就直接退出

拦截器做调整

service.interceptors.response.use(
	response => {
		// 如果之前进入过拦截器钩子, 那么 response 实际上就已经是 response.data, 直接 return
		if(!(response.request instanceof XMLHttpRequest)){
			return response
		}
		return response.data
	},
	// 错误处理加入防抖, 同样的 error 只执行一次回调
	throttleErrorCallback(error => {
		ElMessage({
			message: error.message,
			type: 'error',
			duration: 3000
		})
	})
)

// 错误处理防抖
function throttleErrorCallback(callback){
	const handledErrors = new WeakSet()
	return error => {
		if(handledErrors.has(error) {
			return Promise.reject(error)
		}
		handledErrors.add(error)
		return callback(error)
	}
}

如果有其他解决 axios-retry 带来的拦截器问题的方式, 欢迎交流

---------2024-3-1--------------------
经过调试, 发现是有个地方代码变量 stop 未使用 let 等声明, 所以直接引用了 window.stop, window.stop 会直接停止页面所有请求, 所以导致异步请求异常中断,此时错误码为 “ECONNABORTED”

### 解决 Axios 请求时遇到的意外文件结束错误 当处理 `axios` 的 `'unexpected end of file'` 错误时,通常意味着服务器响应被截断或未完成。这可能是由于网络连接不稳定、服务器配置不当或其他因素引起的。 #### 可能的原因分析 1. **网络问题** 如果客户端和服务器之间的网络连接不稳定,可能会导致部分数据丢失,从而引发此错误。建议检查网络环境并尝试重新发送请求[^1]。 2. **超时设置不合理** 默认情况下,`axios` 设置了一个合理的超时时间来防止长时间等待无果的情况发生。如果目标资源加载较慢,则可能需要调整超时参数以适应实际情况。 3. **服务端返回异常** 当服务器内部出现问题而未能正常终止HTTP事务时也会抛出此类异常。此时应联系后端开发人员排查是否存在程序崩溃等问题。 4. **跨域资源共享(CORS) 配置不正确** 若前端应用与API接口部署于不同域名下,则需确保CORS策略允许合法访问;否则浏览器会阻止某些类型的请求执行成功。 针对上述情况可以采取如下措施: - 尝试增加请求重试机制,在捕获到特定错误码后再自动发起新一轮调用; - 修改默认timeout选项延长最大等待时限,例如通过全局配置方式实现: ```javascript axios.defaults.timeout = 5000; // 单位毫秒 ``` - 对于生产环境中频繁发生的同类事件记录日志便于后续定位根本原因所在,并及时反馈给运维团队协助解决问题。 另外值得注意的是,对于大型文件下载场景还应该考虑分片传输等优化手段减少单次交互的数据量大小,提高成功率。 ```javascript // 自定义拦截器用于统一处理所有GET/POST操作中的异常状况 axios.interceptors.response.use( response => { return response; }, error => { const originalRequest = error.config; if (error.message === 'Network Error') { alert('网络连接失败'); } else if ( !originalRequest._retry && (error.code === 'ECONNABORTED' || error.message.includes('timeout')) ) { originalRequest._retry = true; return axios(originalRequest); } throw error; } ); // 使用try-catch包裹异步函数体内的await表达式以便更好地捕捉潜在风险点 async function fetchData() { try { let res = await axios.get('/api/data'); console.log(res.data); } catch (err) { console.error(err); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值