【面试题】前端中 JS 发起的请求可以暂停吗?
这个问题非常有意思,我一看到就想了很多可以回复的答案,但是评论区太窄,就直接开一篇文章来写了。
审题
JS 发起的请求可以暂停吗?这一句话当中有两个概念需要明确,一是什么样的状态才能称之为 暂停?二是 JS 发起的请求 是什么?
怎么样才算暂停?
暂停 全称暂时停止,在已开始未结束的过程中临时停止可以称之为暂停,意味着这个过程可以在某个时间点截断然后在另一个时间点重新续上。
请求应该是什么?
这里得先介绍一下 TCP/IP 网络模型, 网络模型自上而下分为 应用层、传输层、网络层和网络接口层。

上图表示的意思是,每次网络传输,应用数据在发送至目标前都需要通过网络模型一层一层的包装,就像寄快递一样,把要寄的物品先打包好登记一下大小,再装在盒子里登记一下目的地,然后再装到车上,最后送往目的地。
请求(Request) 这个概念就可以理解为客户端通过若干次数据网络传输,将单份数据完整发给服务端的行为,而针对某次请求服务端往客户端发送的答复数据则可以称之为 响应(Response)。
理论上应用层的协议可以通过类似于标记数据包序列号等等一系列手段来实现暂停机制。但是 TCP 协议并不支持,TCP 协议的数据传输是流式的,数据被视为一连串的字节流。客户端发送的数据会被拆分成多个 TCP 段(TCP segments),而这些段在网络中是独立传输的,无法直接控制每个 TCP 段的传输,因此也无法实现暂停请求或者暂停响应的功能。

解答提问
如果请求是指网络模型中的一次请求传输,那理所当然是不可能暂停的。
来看看提问者的使用场景 —— JS 发起的请求,那么可以认为问题当中的请求,应该是指在 JS 运行时中发起的 XMLHttpRequest 或者是 fetch 请求,而请求既然已经发起,那问的自然就是 响应是否能够被暂停 。
我们都知道像大文件分片上传、以及分片下载之类的功能本质上是将分片顺序定好之后按顺序请求,然后就可以通过中断顺序并记录中断点来实现暂停重传的机制,而单个请求并不具备这样的环境。
用 JS 实现 ”假暂停” 机制
虽然不能真正意义上实现暂停请求,但是我们其实可以模拟一个 假暂停 的功能,在前端的业务场景上,数据不是收到就可以直接打在客户脸上的(什么光速打击),前端开发者需要对这些数据进行处理之后渲染在界面上,如果我们能在请求发起之前增加一个控制器,在请求回来时,如果控制器为暂停状态则不处理数据,等待控制器恢复后再进行处理,是不是也能到达到目的?让我们试着实现一下。
假如我们使用 fetch 来请求。我们可以设计一个控制器 Promise 和请求放在一起用 Promise.all 包裹,当 fetch 完成时判断这个控制器的暂停状态,如果没有被暂停,则控制器也直接 resolve,同时整个 Promise.all 也 resolve 抛出。
function _request () {return new Promise<number>((res) => setTimeout(() => {res(123)}, 3000))
}// 原本想使用 class extends Promise 来实现
// 结果一直出现这个问题 https://github.com/nodejs/node/issues/13678
function createPauseControllerPromise () {const result = {isPause: false,resolveWhenResume: false,resolve (value?: any) {},pause () {this.isPause = true},resume () {if (!this.isPause) returnthis.isPause = falseif (this.resolveWhenResume) {this.resolve()}},promise: Promise.resolve()}const promise = new Promise<void>((res) => {result.resolve = res})result.promise = promisereturn result
}function requestWithPauseControl <T extends () => Promise<any>>(request: T) {const controller = createPauseControllerPromise()const controlRequest = request().then((data) => {if (!controller.isPause) controller.resolve()return data}).finally(() => {controller.resolveWhenResume = true})const result = Promise.all([controlRequest, controller.promise]).then(data => {controller.resolve()return data[0]});(result as any).pause = controller.pause.bind(controller);(result as any).resume = controller.resume.bind(controller);return result as ReturnType<T> & { pause: () => void, resume: () => void }
}
用法
我们可以通过调用 requestWithPauseControl(_request) 来替代调用 _request 使用,通过返回的 pause 和 resume 方法控制暂停和继续。
const result = requestWithPauseControl(_request).then((data) => {console.log(data)
})if (Math.random() > 0.5) { result.pause() }setTimeout(() => {result.resume()
}, 4000)
最后
以上就是本篇文章分享的全部内容了。
这里是 Xekin(/zi:kin/)。喜欢的掘友们可以点赞关注点个收藏~
最近摸鱼时间比较多,写了一些奇奇怪怪有用但又不是特别有用的工具,不过还是非常有意思的,之后会一一写文章分享出来,感谢各位支持。
前端面试题库 (面试必备) 推荐:★★★★★
地址:前端面试题库
相关文章:
【面试题】前端中 JS 发起的请求可以暂停吗?
这个问题非常有意思,我一看到就想了很多可以回复的答案,但是评论区太窄,就直接开一篇文章来写了。 审题 JS 发起的请求可以暂停吗?这一句话当中有两个概念需要明确,一是什么样的状态才能称之为 暂停?二是…...
通过社区参与解锁早期增长:Maven 远程医疗平台概览
Maven通过用户导向的渐进式验证,找到了一个被忽视的巨大女性医疗服务市场,作为女性医疗保健的先行者,已服务超过1500万用户,目前估值已达$14亿。本文将深入探索Maven实现产品市场匹配的三个阶段,从如何验证初始的市场机…...
Vue中使用echarts
1 安装 npm install -g cnpm --registryhttps://registry.npm.taobao.org cnpm install echarts -S 2 main.js引入 3 引入成功...
边缘计算对现代交通的重要作用
边缘计算之所以重要,是在于即使在5G真正商用之时,可以实现超大带宽(eMBB)的应用场景,但庞大数据量的涌现也就意味着需要在云和端传输过程中找到一个承接点,对数据进行预处理再选择是否上云。 边缘计算应用演…...
Python桥接模式介绍、使用
一、Python桥接模式介绍 概念: Python桥接模式(Bridge Pattern)是一种软件设计模式,用于将抽象部分与其实现部分分离,使它们可以独立地变化。 它可以通过使用桥接接口来创建一个桥接对象来连接抽象和实现部分。 功能…...
ChatGPT在知识图谱的构建和更新中的应用如何?
ChatGPT在知识图谱的构建和更新中具有重要的应用潜力。知识图谱是一种用于表示和存储结构化知识的图形化数据模型,通常由实体、属性和关系组成。知识图谱的构建和更新是一个复杂而关键的过程,涉及知识的收集、组织、链接和推理。ChatGPT作为一种预训练语…...
JS正则表达式:常用正则手册/RegExp/正则积累
一、正则基础语法 JavaScript 正则表达式 | 菜鸟教程 JS正则表达式语法大全(非常详细) 二、使用场景 2.1、校验中国大陆手机号的正则表达式 正则 /^1[3456789]\d{9}$/解释 序号正则解释1^1以数字 1 开头2[3456789]第二位可以是 3、4、5、6、7、8、…...
自动化测试框架unittest与pytest的区别!
引言 前面文章已经介绍了python单元测试框架,大家平时经常使用的是unittest,因为它比较基础,并且可以进行二次开发,如果你的开发水平很高,集成开发自动化测试平台也是可以的。而这篇文章主要讲unittest与pytest的区别&…...
【Git】
学习来自于: 女朋友乱用Git,差点把我代码删了。。。 一些常用的Git 知识点整理 关于Git这一篇就够了 Git基本命令大全 30分钟精通Git,学不会来找我 Git 版本管理 | 莫烦PYTHON Git 代码版本管理教程 文章目录 【前言】集中式与分布式的…...
[论文笔记] CLRerNet: Improving Confidence of Lane Detection with LaneIoU
Honda, Hiroto, and Yusuke Uchida. “CLRerNet: Improving Confidence of Lane Detection with LaneIoU.” arXiv preprint arXiv:2305.08366 (2023). 2023.05 出的一篇车道线检测的文章, 效果在CULane, CurveLanes SOTA 文章目录 简介LaneIoULineIoU存在问题为什么使用LaneIo…...
LeetCode|backtracking|review:40. 131. 93. 47. 332. | 37. Sudoku Solver
复习: 40. Combination Sum II [1,1,2,3]中,答案里有[1,1,2], 但是不能有两个[1,2,3] 131. Palindrome Partitioning 每个for都是在给定的start之后找一个palindrome。当start 93. Restore IP Addresses forloop每次loop都是在给定的start的后三个数…...
被泼冷水后,谁能超越微服务?
历史总会重演。一切刚过去的,又会被重新提起。开源项目Codename One的联合创始人Shai,曾是Sun Microsystems开源LWUIT项目的共同作者,参与了无数开源项目。作为最早一批Java开发者,最近感慨道:单体,又回来了…...
多线程(JavaEE初阶系列5)
目录 前言: 1.什么是定时器 2.标准库中的定时器及使用 3.实现定时器 结束语: 前言: 在上一节中小编给大家介绍了多线程中的两个设计模式,单例模式和阻塞式队列模式,在单例模式中又有两种实现方式一种是懒汉模式&a…...
Minimum Snap闭式求解相关公式推导
文章目录 1 M i n i m u m Minimum Minimum S n a p Snap Snap闭式求解的推导1.1 二次规划等式约束构建1.2 求 d d d1.3 转成无约束优化问题 1 M i n i m u m Minimum Minimum S n a p Snap Snap闭式求解的推导 可以看看我的这几篇Blog1,Blog2,Blog…...
Spring源码(五)— 解析XML配置文件(一) bean标签解析流程
前面几章的内容已经介绍了BeanFactory创建前的准备工作,以及加载XML配置文件前的准备的步骤。本章会着重介绍解析XML的步骤。 registerBeanDefinitions 前几个方法不做过多的赘述,着重看registerBeanDefinitions方法中解析XML的步骤。 public int regi…...
隐私政策声明
http://lxfamn.cn/tools 我们注重对您个人隐私的保护。有时候我们需要某些信息才能为您提供您请求的服务,本隐私声明解释了这些情况下的数据收集和使用情况。本隐私声明适用于本网站的所有相关服务。如果您访问本网站、使用本网站的任何服务,那么您便接受…...
Flutter 最佳实践和编码准则
Flutter 最佳实践和编码准则 视频 前言 最佳实践是一套既定的准则,可以提高代码质量、可读性和可靠性。它们确保遵循行业标准,鼓励一致性,并促进开发人员之间的合作。通过遵循最佳实践,代码变得更容易理解、修改和调试ÿ…...
LangChain Agents深入剖析及源码解密上(一)
LangChain Agents深入剖析及源码解密上(一) LangChain Agents深入剖析及源码解密上 Agent工作原理详解 本节会结合AutoGPT的案例,讲解LangChain代理(Agent)为核心的内容。我们前面已经谈了代理本身的很多内容,也看了绝大部分的源代码,例如:ReAct的源代码,还有mrkl的源代…...
css定义超级链接a标签里面的title的样式
效果: 代码: 总结:此css 使用于任何元素,不仅仅是a标签!...
hcip——路由策略
要求: 基础配置 AR1 [R1]int g 0/0/0 [R1-GigabitEthernet0/0/0]ip add 12.0.0.1 24[R1-GigabitEthernet0/0/0]int g 0/0/1 [R1-GigabitEthernet0/0/1]ip add 14.0.0.1 24[R1]int loop0 [R1-LoopBack0]ip add 1.1.1.1 24[R1]rip 1 [R1-rip-1]vers 2 [R1-rip-1]net…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
