JavaScript 中断请求的几种方法

中断Promise

中断Promise不等同于中止Promise,因为Promise是无法被终止的.

这里的中断指的是,在合适的时机,把pending状态的promise给reject掉。例如一个常见的应用场景就是给网络请求设置超时时间,一旦超时就中断。

还是用 setTimeout 来模拟网络请求。阀值设置为Math.random() * 3000表示随机3秒之内返回结果。

const request = new Promise((resolve, reject) => {setTimeout(() => {resolve('收到服务端数据')}, Math.random() * 3000)
});

假设超过2秒就是网络超时,我们可以封装一个超时处理函数。
由于网络请求所需的事件是随机的,因此可以利用Promise.race(race方法返回第一个异步任务完成时,并不关心它的最终状态 即它可以成功也可以失败)方法,达到超时reject的目的。

const timeoutReject = (p1, timeout = 2000) => {const p2 = new Promise((resolve, reject) => {setTimeout(() => {reject('网络超时');}, timeout);});return Promise.race([p1, p2]);
};timeoutReject(request).then(res => {console.log(res);
}).catch(err => {console.log(err);
});

包装cancel方法——仿照Axios的CancelToken

上面实现的方式并不灵活,因为中断Promise的方式有很多,不单单是网络超时.
我们可以仿照Axios中CancelToken的核心源码,简单包装一个cancel方法,供使用者随时调用.

function cancelWrapper(p1) {let cancel;const p2 = new Promise((resolve, reject) => {cancel = reject;});// 如果没有resolve或reject,p2的状态永远是pendingconst p = Promise.race([p1, p2]);p.cancel = cancel;return p;
}const req = cancelWrapper(request);
req.then(res => {console.log(res);
}).catch(err => {console.log(err);
});setTimeout(() => {// 手动调用req.cancel,将p2的状态改变为rejectedreq.cancel('手动中断请求');
}, 2000);

如此封装的主要目的就是为了能够在Promise外部控制其resolve或reject,让使用者可以随时手动调用resolve(触发.then)或reject(触发.catch)。

又或者我们换个写法:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Document</title>
</head>
<body>
<button id="send">Send</button>
<button id="cancel">Cancel</button><script>class CancelToken {constructor(cancelFn) {this.promise = new Promise((resolve, reject) => {cancelFn(() => {resolve("delay cancelled");});});}}const sendButton = document.querySelector("#send");const cancelButton = document.querySelector("#cancel");function cancellableDelayedResolve(delay) {console.log("prepare send request");return new Promise((resolve, reject) => {const id = setTimeout(() => {console.log("ajax get data");}, delay);const cancelToken = new CancelToken((cancelCallback) => {cancelButton.addEventListener("click", cancelCallback);});cancelToken.promise.then((res) => {console.log('cancelToken', res);clearTimeout(id);});});}sendButton.addEventListener("click", () => {cancellableDelayedResolve(2000).then(res => {console.log(res);});});
</script>
</body>
</html>

在上面的案例中,我们是先预置一个 promise,也就是 CancelToken,它的作用就是在需要的时候能够随时调用 并在其中加关闭逻辑。

上面我们提到了Axios 的 CancelToken,接下来我们来看下:
方法1:

import axios from 'axios';
const CancelToken = axios.CancelToken;
const source = CancelToken.source();axios.get('/user/12345', {cancelToken: source.token
}).catch(function (thrown) {if (axios.isCancel(thrown)) {console.log('Request canceled', thrown.message);} else {// handle error} 
});source.cancel('Operation canceled by the user.');

方法2:

import axios from 'axios';
const CancelToken = axios.CancelToken;// 创建一个变量如 cancel 用于存储这个中断某个请求的方法
let cancel;axios.get('/user/12345', {cancelToken: new CancelToken(function executor(c) {cancel = c; // 将参数 c 赋值给 cancel})
});// 判断 cancel 是否为函数,确保 axios 已实例化一个CancelToken
if (typeof cancel === 'function') {cancel();cancel = null;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/694363.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1027. 最长等差数列【leetcode】/动态规划

1027. 最长等差数列 给你一个整数数组 nums&#xff0c;返回 nums 中最长等差子序列的长度。 回想一下&#xff0c;nums 的子序列是一个列表 nums[i1], nums[i2], …, nums[ik] &#xff0c;且 0 < i1 < i2 < … < ik < nums.length - 1。并且如果 seq[i1] - …

《Linux C编程实战》笔记:消息队列

消息队列是一个存放在内核中的消息链表&#xff0c;每个消息队列由消息队列标识符标识。与管道不同的是消息队列存放在内核中&#xff0c;只有在内核重启&#xff08;即操作系统重启&#xff09;或显示地删除一个消息队列时&#xff0c;该消息队列才会被真正的删除。 操作消息…

OPPO公布全新AI战略,AI 手机时代再提速

2024年2月20日&#xff0c;深圳——今日OPPO 举办 AI 战略发布会&#xff0c;分享新一代 AI 手机的四大能力特征&#xff0c;展望由AI驱动的手机全栈革新和生态重构的趋势&#xff0c;并发布由OPPO AI 超级智能体和 AI Pro 智能体开发平台组成的OPPO 1N 智能体生态战略&#xf…

Android基础Adapter适配器详解

一、概念 Adapter是后端数据和前端显示UI的适配器接口。常见的View如ListView、GridView等需要用到Adapter. BaseAdapter&#xff1a;抽象类&#xff0c;实际开发中继承这个类并且重写相关方法&#xff0c;用得最多的一个Adapter&#xff01; ArrayAdapter&#xff1a;支持泛型…

人工智能数学验证工具LEAN4【入门介绍7】高级加法世界-如何进行分类讨论

视频链接&#xff1a;人工智能数学验证工具LEAN4【入门介绍7】高级加法世界-如何进行分类讨论_哔哩哔哩_bilibili import Game.Levels.AdvAddition.L05add_right_eq_zero World "AdvAddition" Level 6 Title "add_left_eq_zero" TheoremTab ""…

[知识点]务必记住isBlank和isEnpty的区别!!!

身为一个伟大的程序员,我不允许你不懂isBlank和isEmpty的区别 正文 StrUtil.isBlank(message)和StrUtil.isEmpty(message)这两个方法都是用来检查一个字符串是否为空&#xff0c;但它们的行为是不同的&#xff1a; StrUtil.isEmpty(message)&#xff1a;这个方法会检查字符串是…

数字化商品管理:革新鞋服零售模式,引领智能商业新时代

随着科技的快速发展&#xff0c;数字化浪潮席卷各行各业&#xff0c;鞋服零售企业亦不例外。在这个新时代&#xff0c;数字化商品管理不仅成为鞋服零售企业革新的关键&#xff0c;更是其引领智能商业浪潮的重要引擎。本文将围绕数字化商品管理如何深刻影响鞋服零售模式&#xf…

力扣 309. 买卖股票的最佳时机含冷冻期

题目来源&#xff1a;https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-cooldown/description/ C题解&#xff1a;动态规划 状态1&#xff1a;表示持有股票。更新为之前持有股票&#xff08;dp[i-1][0]&#xff09;或者不持有股票且不处于冷冻期后买入&…

Qt标准对话框设置

Qt标准对话框设置&#xff0c;设置字体、调色板、进度条等。 #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this); }MainWindow::~MainWi…

make_shared_for_overwrite

这个函数用来malloc数组&#xff0c;但不初始化。 不过这个仅限于内置类型。如果是用户写的&#xff0c;就会增加自动初始化&#xff08;调用客户写的初始化&#xff09;。

Java基于SSM的羽毛球馆管理系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

[word] word带圈数字20以上 #笔记#笔记

word带圈数字20以上 办公中有时候需要用到带圈数字&#xff0c;超过20的数字就不能直接编辑了&#xff0c;那么20以上带圈数字要怎么输入呢&#xff1f;其实通过小技巧就能完成的&#xff0c;接下来就给大家介绍下呢&#xff0c;一起看看吧&#xff01; 20以上带圈数字输入技巧…

Docker Compose 配置环境变量

在 Docker Compose 中, 可以通过 environment 字段来设置环境变量. 可以在 docker-compose.yml 文件中的服务定义中添加以下行来设置环境变量: services:myservice:environment:- "MY_VAR: myvalue"在这个例子中, myservice 服务的环境变量 MY_VAR 的值被设置为 myv…

Rust语言之异步写文件

文章目录 一、为什么用异步二、如何实现异步1.cargo.toml中引入Tokio2.代码实例 一、为什么用异步 将较与同步操作&#xff0c;异步操作则是非阻塞式的&#xff0c;当程序执行到异步操作时&#xff0c;它会立即返回并继续执行后续的代码&#xff0c;而不会等待该操作的完成。尤…

Java Swing游戏开发学习1

不使用游戏引擎&#xff0c;只使用Java SDK开发游戏的学习。 游戏原理 图片来自某大佬视频讲解 原理结合实际代码 public class GamePanel extends Jpanel implements Runnable {...run(){}// 详情看下图... }项目结构 运行效果 代码code 在我的下载里面可以找到&#xf…

devc++ 使用 winsock 实现 UDP 局域网 WIFI 广播

参考链接 使用UDP发送广播报_udp广播 inaddr_broadcast-CSDN博客 UDP接收端收不到广播的消息问题排查_unity upd广播连接不上是什么情况-CSDN博客 如何禁用自己电脑的虚拟网卡-百度经验 (baidu.com) 但是wifi 会屏蔽255.255.255.255 广播地址&#xff0c;所以 255.255.255.2…

USART(串口发送接受单字节)

一、硬件 差分信号不需要太大的压差。在相同的电磁干扰的环境下&#xff0c;因为是双扭线&#xff0c;两根线受干扰的程度是一样的&#xff0c;所以压差相对不变。提高抗干扰能力。485是双绞线传输取的是两线的压差。一般来说受干扰后同步变化&#xff0c;比如都升0.5V或都降5…

PROBIS铂思金融破产后续:ASIC牌照已注销

2024年1月31日&#xff0c;PROBIS铂思金融的澳大利亚ASIC牌照 (AFSL 338241) 被注销《差价合约经纪商PROBIS宣布破产&#xff0c;澳大利亚金融服务牌照遭暂停》&#xff0c;这也就意味着&#xff0c;PROBIS铂思金融目前已经没有任何金融牌照。 值得注意的是&#xff0c;时至今日…

k8s组件证书续期

K8S 各个组件需要与 api-server 进行通信,通信使用的证书都存放在 /etc/kubernetes/pki 路径下,由 kubeadm 生成的客户端证书在 1 年后到期,因此需要定时更新证书,否则证书到期会导致整个集群不可用。 证书过期后,执行kubectl命令会报如下错误: [root@k8s-master65 ~]#…

【Spring连载】使用Spring Data访问 MongoDB(四)----对象映射Object Mapping

【Spring连载】使用Spring Data访问 MongoDB&#xff08;四&#xff09;----对象映射Object Mapping 一、JSON Schema二、基于类型的转换器三、属性转换器四、非包装类型五、对象引用5.1 使用DBRefs 六、创建索引 一、JSON Schema 二、基于类型的转换器 三、属性转换器 四、…