当前位置: 首页 > news >正文

【前端】在 TypeScript 中使用 AbortController 取消异步请求

在 TypeScript 中使用 AbortController 来取消异步请求,尤其是像 fetch 这样的请求,可以提供一种优雅的方式来中止长时间运行的操作。下面是一个详细的步骤说明,展示如何在 TypeScript 中使用 AbortController 取消 fetch 请求。

步骤 1:创建 AbortController 实例

首先,你需要创建一个 AbortController 实例,并从中获取 signal 对象。这个 signal 对象将在请求中使用,以便在需要时取消请求。

const controller = new AbortController();
const signal = controller.signal;

步骤 2:发送带有 signal 的请求

当使用 fetch 发送请求时,传递 signal 作为选项的一部分。如果请求被取消,fetch 将会抛出一个带有 name 属性为 "AbortError" 的错误。

fetch('/api/data', { signal }).then(response => {if (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);}return response.json();}).then(data => {console.log(data);}).catch(error => {if (error.name === 'AbortError') {console.log('Fetch operation was aborted');} else {console.error('Fetch operation failed:', error);}});

步骤 3:取消请求

在某个时刻,如果你决定要取消请求,只需调用 controller.abort() 方法即可。

setTimeout(() => {controller.abort();
}, 3000); // 取消请求将在3秒后发生

示例:完整的代码示例

下面是一个完整的示例,展示了如何使用 AbortController 来取消一个 fetch 请求:

// 示例:使用 AbortController 取消 fetch 请求
const controller = new AbortController();
const signal = controller.signal;// 在3秒后取消请求
setTimeout(() => {controller.abort();
}, 3000);// 发送带有 signal 的请求
fetch('/api/data', { signal }).then(response => {if (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);}return response.json();}).then(data => {console.log('Received data:', data);}).catch(error => {if (error.name === 'AbortError') {console.log('Fetch operation was aborted');} else {console.error('Fetch operation failed:', error);}});

在使用 AbortController 取消请求后,如果需要重新尝试发送请求,可以采用几种不同的策略。下面将介绍如何在 TypeScript 中实现重新尝试的逻辑。

1. 手动重新尝试

最简单的方法是在请求被取消后手动重新触发请求。这种方法适用于你知道何时应该重新尝试的情况,比如在某些用户操作之后。

const controller = new AbortController();
const signal = controller.signal;// 发送带有 signal 的请求
fetch('/api/data', { signal }).then(response => {if (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);}return response.json();}).then(data => {console.log('Received data:', data);}).catch(error => {if (error.name === 'AbortError') {console.log('Fetch operation was aborted');// 手动重新尝试setTimeout(() => {controller = new AbortController();signal = controller.signal;fetch('/api/data', { signal }).then(response => {if (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);}return response.json();}).then(data => {console.log('Retried and received data:', data);}).catch(error => {console.error('Retry failed:', error);});}, 5000); // 5秒后重新尝试} else {console.error('Fetch operation failed:', error);}});
2. 使用重试库

另一种方法是使用重试库,例如 p-retry 或者 retry,它们可以自动处理重试逻辑,并提供灵活的配置选项。

示例:使用 p-retry

首先安装 p-retry

npm install p-retry

然后在代码中使用它:

import retry from 'p-retry';async function fetchData(signal: AbortSignal): Promise<any> {return fetch('/api/data', { signal }).then(res => res.json());
}retry(() => fetchData(signal),{ retries: 3, factor: 2, minTimeout: 1000, maxTimeout: 3000 }
).then(data => {console.log('Received data:', data);}).catch(error => {console.error('Fetch operation failed:', error);});
3. 自定义重试逻辑

你也可以自己编写重试逻辑,根据需要调整重试次数、间隔时间等参数。

const MAX_RETRIES = 3;
const RETRY_INTERVAL = 1000; // 间隔时间(毫秒)async function fetchData(signal: AbortSignal): Promise<any> {return fetch('/api/data', { signal }).then(res => res.json());
}async function retryFetch(signal: AbortSignal, retriesLeft: number = MAX_RETRIES): Promise<any> {try {return await fetchData(signal);} catch (error) {if (error.name === 'AbortError' && retriesLeft > 0) {console.log(`Fetch operation was aborted, retrying... (${retriesLeft} attempts left)`);await new Promise(resolve => setTimeout(resolve, RETRY_INTERVAL));return retryFetch(signal, retriesLeft - 1);} else {throw error;}}
}retryFetch(signal).then(data => {console.log('Received data:', data);}).catch(error => {console.error('Fetch operation failed:', error);});
4. 使用 AbortController 的组合策略

你还可以结合使用 AbortController 和重试逻辑,以实现更复杂的场景。例如,在某些条件下取消请求,并在满足一定条件时重新尝试。

const controller = new AbortController();
const signal = controller.signal;// 在满足某些条件下取消请求
setTimeout(() => {if (/* 某些条件 */) {controller.abort();}
}, 3000);// 发送带有 signal 的请求
fetch('/api/data', { signal }).then(response => {if (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);}return response.json();}).then(data => {console.log('Received data:', data);}).catch(error => {if (error.name === 'AbortError') {console.log('Fetch operation was aborted');// 根据条件重新尝试if (/* 满足重新尝试的条件 */) {const newController = new AbortController();const newSignal = newController.signal;fetch('/api/data', { signal: newSignal }).then(response => {if (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);}return response.json();}).then(data => {console.log('Retried and received data:', data);}).catch(error => {console.error('Retry failed:', error);});}} else {console.error('Fetch operation failed:', error);}});

注意事项

  • 兼容性:请确保你的浏览器或 Node.js 版本支持 AbortController。对于不支持的环境,你可能需要考虑使用 polyfills。
  • 信号传播:如果你在请求中使用了中间件(例如代理服务器),请注意 AbortController 的信号可能不会被正确传播。在这种情况下,你可能需要手动处理信号的传播。
  • 资源释放:取消请求后,确保适当释放资源。例如,如果请求涉及文件上传,取消请求后应确保删除临时文件。

使用 AbortController 的好处

  • 更好的用户体验:用户可以在长时间的请求未完成前取消请求,减少无响应的情况。
  • 资源管理:可以避免因长时间未完成的请求而导致的资源浪费。
  • 灵活性:为异步操作提供了一种灵活的控制机制。

通过这种方式,你可以有效地在 TypeScript 中使用 AbortController 来管理异步请求的生命周期。

http://www.lryc.cn/news/472906.html

相关文章:

  • k8s知识点总结
  • 论文阅读:三星-TinyClick
  • Windows on ARM上使用sherpa-onnx实现语音识别
  • Unity 打包AB Timeline 引用丢失,错误问题
  • 【Kettle的安装与使用】使用Kettle实现mysql和hive的数据传输(使用Kettle将mysql数据导入hive、将hive数据导入mysql)
  • STM32的hal库在实现延时函数(例如:Delay_ms 等)为什么用滴答定时(Systick)而不是定时器定时中断,也不是RTC?
  • 刚刚买的域名被DNS劫持了怎么处理
  • 递归 算法专题
  • Logstash 迁移索引元数据(设置和映射)
  • 用python将pdf转成图片转换成对应的word文件
  • list(c++)
  • 51单片机STC8G串口Uart配置
  • uni-app使用movable-area 实现数据的拖拽排序功能
  • 如何设置使PPT的画的图片导出变清晰
  • 和鲸科技 CEO 范向伟受邀揭牌启动南京大学 2024 级大学生人工智能素养大赛
  • NewStarCTF2024-Week4-Web-WP
  • Java学习Day56:暴打舔狗!(SpringBoot)
  • RSA加密算法实现
  • 大数据新视界 -- 大数据大厂之优化大数据计算框架 Tez 的实践指南
  • java 中 List<T> 类型数据在 postgreSql 数据库中存储
  • 公共命名空间,2024年10月的笔记
  • frida脚本,自动化寻址JNI方法
  • ‌MySQL中‌between and的基本用法‌
  • Ceph 存储系统全解
  • C# ftp帮助类 项目实战优化版
  • 栈和队列相关|有效的括号|用队列实现栈|用栈实现队列|设计循环队列(C)
  • 云原生后端开发教程
  • TortoiseSVN小乌龟下载安装(Windows11)
  • Android adb命令获取设备id
  • Skywalking教程一