请求中断
场景:
1、假如一个页面接口太多、或者当前网络太卡顿、这个时候跳往其他路由,
当前页面可以做的就是把请求中断掉(优化)
2、假如当前接口调取了第一页数据,又调去了第二页的数据,
当我们调取第二页数据时就需要把第一页数据的请求中断掉
(常见于在搜索大数据)
3、取消下载
原理:
AbortController 接口表示一个控制器对象,允许你根据需要中止一个或多个 Web 请求
技术:axios+vue3.0模拟
-
实现
1、将中止控制器传递给 axios 的 调去接口的方法controller = new AbortController() 2、axios里面有定义标识的属性signal 3、点击事件:controller.abort()
js<script setup lang="ts"> import axios from 'axios' import { ref } from 'vue' const progress = ref(0) // 进度条百分比 let controller: AbortController // 中止控制器 // 中止下载 const abortDownload = () => { if (controller) { controller.abort() // 使用 abort 方法中止下载 console.log('中止下载') } } // 下载视频 const fetchVideo = () => { controller = new AbortController() // 创建 AbortController axios({ // 将中止控制器传递给 axios 的 get 方法 method: 'GET', url: 'http://localhost:3000/video', signal: controller.signal, responseType: 'arraybuffer', onDownloadProgress: (progressEvent) => { // 计算进度百分比 progress.value = Math.round((progressEvent.loaded / progressEvent.total!) * 100) } }) .then((response) => { console.log('下载完成', response) // ✅ 保存下载的文件 const { buffer } = new Uint8Array(response.data) const blob = new Blob([buffer], { type: 'application/octet-stream' }) const link = document.createElement('a') // 创建链接元素 link.href = URL.createObjectURL(blob) // 将 Blob 对象转换为 URL link.download = 'video.mp4' // 设置文件名 link.click() // 模拟点击链接元素 }) .catch((err) => { if (axios.isCancel(err)) { console.log('下载被取消') } else if (err.name === 'AbortError') { console.log('下载被中止') } else { console.error(`下载错误:${err.message}`) } }) } </script> <template> <div> <button class="download" @click="fetchVideo">下载视频</button> <button class="abort" @click="abortDownload">中止下载</button> <div class="progress-bar"> <div class="progress" :style="{ width: progress + '%' }"></div> {{ progress }}% </div> </div> </template> <style scoped> .progress-bar { height: 20px; background-color: #eee; margin-top: 10px; } .progress { width: 0%; height: 100%; background-color: #4caf50; transition: width 0.2s linear; } </style>
请求重试
场景:
当用户访问我们的 Web 应用程序时,HTTP 请求可能会由于网络不稳定而失败,例如超时或网络异常。
模拟 axios timeout: 2000,服务端加个延时3s。
axios里面设置两个参数:{
retries: 3, // 设置重试次数为3次
retryDelay: 1000, // 设置重试的间隔时间
}
在响应拦截返回失败时进行重试:设置重试次数的参数,再次发送请求
使用 Axios 的拦截器拦截响应,则尝试再次发送请求,通过设置 retry 和 retryDelay 来控制重试请求的数量和每个请求之间的间隔。
```js
<script setup lang="ts">
import axios from 'axios'
const request = axios.create({
baseURL: 'http://localhost:3000',
// 设置请求超时时间为5秒
timeout: 2000,
retries: 3, // 设置重试次数为3次
retryDelay: 1000, // 设置重试的间隔时间
} as any)
// 添加响应拦截器
request.interceptors.response.use(
(response) => {
// 对响应数据做些什么
return Promise.resolve(response.data)
},
(error) => {
const config = error.config
// 如果config不存在或未设置重试选项,则拒绝
if (!config || !config.retries) {
return Promise.reject(error)
}
// 设置变量来跟踪重试次数
config.__retryCount = config.__retryCount || 0
// 检查是否达到最大重试次数
if (config.__retryCount >= config.retries) {
return Promise.reject(error)
}
// 增加重试计数器
config.__retryCount += 1
// 创建一个新的Promise来处理每次重试之前等待一段时间
const backoff = new Promise((resolve) => {
setTimeout(() => {
resolve('重新请求:' + config.__retryCount)
}, config.retryDelay || 1)
})
// 返回Promise,以便Axios知道我们已经处理了错误
return backoff.then((txt) => {
console.log(txt)
return request(config)
})
},
)
// 请求中止控制器
let controller: AbortController
// --- 获取数据 ---
const getData = async () => {
controller = new AbortController()
const res = await request({
signal: controller.signal, // 添加请求中止标识
method: 'GET',
url: '/delay_3s_data',
})
console.log('成功获取数据', res)
}
const stop = () => {
// 中止网络请求
controller.abort()
}
</script>
<template>
<h1>axios请求重试</h1>
<button @click="getData()">发送请求</button>
<button @click="stop()">中止请求</button>
</template>
axios-retry 插件
插件可以更方便实现请求重试
npm install axios-retry
导入以下数据就可以了
// axios-retry 插件
axiosRetry(request, {
retries: 3, // 设置重试次数
retryDelay: () => 500, // 设置重试延迟时间
shouldResetTimeout: true, // 重置请求超时时间
// error.code===ECONNABORTED表示请求超时了 ERR_NETWORK网络出错
retryCondition: (error) => ['ECONNABORTED', 'ERR_NETWORK'].includes(error.code!), // 重试条件
})
js
<script setup lang="ts">
import axios from 'axios'
import axiosRetry from 'axios-retry'
const request = axios.create({
baseURL: 'http://localhost:3000',
timeout: 2000,
})
// axios-retry 插件
axiosRetry(request, {
retries: 3, // 设置重试次数
retryDelay: () => 500, // 设置重试延迟时间
shouldResetTimeout: true, // 重置请求超时时间
retryCondition: (error) => ['ECONNABORTED', 'ERR_NETWORK'].includes(error.code!), // 重试条件
})
// 请求中止控制器
let controller: AbortController
// --- 获取数据 ---
const getData = async () => {
// 请求控制器
controller = new AbortController()
const res = await request({
method: 'GET',
url: '/delay_3s_data',
signal: controller.signal, // 添加请求中止标识
})
console.log('成功获取数据', res)
}
const stop = () => {
// 中止网络请求
controller.abort()
}
</script>
<template>
<h1>axios请求重试-axiosRetry</h1>
<button @click="getData()">发送请求</button>
<button @click="stop()">中止请求</button>
</template>