新颖的 setTimeout() 替代方案

在前端开发中,长时间运行的JavaScript任务一直是一个棘手的问题。它们会导致页面无响应,影响用户体验。传统上,开发者使用setTimeout()来分割长任务,但这种方法存在明显的缺陷。最近,Chrome 129引入了一种新的、更高效的方法:scheduler.yield()。本文将深入探讨这种新技术,并比较其与传统方法的优劣。

长任务的问题

为了说明长任务的问题,以下是一个示例,任何字符都有其代码,但并非所有代码都有相关字符。所有非字符代码都显示为白色垂直矩形。您可以在下面显示与一系列代码相对应的字符的页面中看到许多代码:

2b4778af552da00c013c3215002f370d.png

有很多垂直的矩形,想把它们过滤掉,通过遍历一系列Unicode字符代码,过滤掉未分配的代码点。

const MIN = 127734, MAX = 129686;function insertChar(code, parent) {parent.insertAdjacentText('beforeend', String.fromCodePoint(code));
}function add(i, parent) {if (!likeNull(i)) // 比较字符i和0的canvasinsertChar(i, parent);
}function one(div) {for (let i = MIN; i < MAX; i++)add(i, div);
}function onClick(func) {btn.addEventListener('click', async () => {btn.remove();const start = Date.now();await func(div);div.insertAdjacentText("afterend", Date.now() - start);});
}onClick(one);

8a6d08c57c12bf3be8b0a65c9d9230b4.gif

这段代码在执行过程中会使页面冻结约4279毫秒,而在此期间,页面一直处于冻结状态。即使点击后代码会首先移除按钮,但只要代码还在运行,浏览器就无法更新屏幕。代码运行结束后,浏览器也无法显示任何字符,按钮会被移除,字符也会一并显示, 导致用户体验不佳。

因此,在长时间工作时,一定要暂停,让浏览器更新屏幕。可以使用类似的语句暂时中止或中断长代码的执行.

使用setTimeout()分割任务

传统的解决方法是使用setTimeout()来分割任务:

function pause() {return new Promise(resolve => setTimeout(resolve));
}async function two(div) {for (let i = MIN; i < MAX; i++) {await pause();add(i, div);}
}onClick(two);

5ee547f907d84bd5805934cb291b6dca.png

这种方法虽然使页面保持响应,但执行时间显著增加到约17568毫秒。

setTimeout()的缺点

1.最小超时时间为4毫秒,即使指定为0

即使浏览器无事可做,主任务也会暂停至少 4 毫秒。即使指定为零,setTimeout()的最小超时时间 也是 >4 ms。事实上,让我们来计算一下。在第一页中,评估 1952 个代码点需要 4279 毫秒,即每个代码需要 ~2 毫秒。在第二个页面中,评估 1952 个代码点需要 17568 毫秒,即每个代码点 ~17568/1952=9毫秒。页面响应速度保持不变,但性能下降也令人印象深刻,这主要是由于超时的持续时间尽可能短。

2.任务继续执行时被放置在队列末尾,可能导致优先级问题。

当任务暂停时,setTimeout() 会将其作为一个新任务放置在队列的最末端。因此,浏览器不仅会更新屏幕,还会先执行队列中的所有任务,然后再继续执行暂停的任务。

ff194ab261784e978a308aa0e537d026.gif

在上面的页面中,两个函数two()同时运行:

onClick(()=>Promise.race([two(div),two(div2)]));

当第一个two()提交给主线程时,第二个two()会在第一个two()继续执行之前被执行。执行时间会稍有增加,从 17 秒增加到 23 秒,但不会增加两倍,因为大部分运行时间都是由最小超时加起来的。

scheduler.yield():新的解决方案

scheduler.yield()提供了一种更高效的方法来让出主线程:

async function three(div) {for (let i = MIN; i < MAX; i++) {await scheduler.yield();add(i, div);}
}onClick(three);

a25ecc1864b86fe54555edaa9b710caa.jpeg

使用scheduler.yield(),执行时间减少到约5646毫秒,显著优于setTimeout()方法。

scheduler.yield()的优势

  1. 更高的性能:执行时间更接近于未中断的任务。

  2. 优先级处理:被暂停的任务被放置在队列头部,而不是末尾。

示例比较:

// 同时执行两个three()函数
onClick(() => Promise.race([three(div), three(div2)]));// three()与setTimeout()基于的two()比较
onClick(() => Promise.race([three(div), two(div2)]));

结果与上述基于setTimeout()的index4.html的不同之处仅在于执行时间。10183 毫秒相当于两次 5645 毫秒。两个任务似乎都没有优先级。

优先级似乎不起作用,因为两个函数three()都不在队列中等待。但看看这个:

03e57751863a8aab99077b3e6a313136.gif

在与setTimeout()基于的方法比较时,scheduler.yield()显示出明显的优先级优势。

结语

scheduler.yield()为JavaScript中的任务调度提供了一个强大的新工具。它不仅性能更优,还能更好地处理任务优先级。对于需要处理长时间运行任务的前端开发者来说,这是一个值得关注和采用的新技术。

在实际应用中,开发者可以考虑在处理大量数据处理、复杂计算或频繁DOM操作等场景时使用scheduler.yield()。这将有助于保持页面的响应性,同时不会显著影响任务的执行效率。随着浏览器支持的增加,scheduler.yield()有望成为前端性能优化的重要工具。

最后:

React Hook 深入浅出

CSS技巧与案例详解

vue2与vue3技巧合集

VueUse源码解读

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

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

相关文章

机器学习面试笔试知识点-线性回归、逻辑回归(Logistics Regression)和支持向量机(SVM)

机器学习面试笔试知识点-线性回归、逻辑回归Logistics Regression和支持向量机SVM 一、线性回归1.线性回归的假设函数2.线性回归的损失函数(Loss Function)两者区别3.简述岭回归与Lasso回归以及使用场景4.什么场景下用L1、L2正则化5.什么是ElasticNet回归6.ElasticNet回归的使…

视频云存储/音视频流媒体视频平台EasyCVR视频汇聚平台在欧拉系统中启动失败是什么原因?

视频监控/视频集中存储/磁盘阵列EasyCVR视频汇聚平台具备强大的拓展性和灵活性&#xff0c;支持多种视频流的外部分发&#xff0c;如RTMP、RTSP、HTTP-FLV、WebSocket-FLV、HLS、WebRTC、fmp4等&#xff0c;这为其在各种复杂环境下的部署提供了便利。 安防监控EasyCVR视频汇聚平…

分布式数据库安全可靠测评名录之平凯数据库(TiDB企业版)

作者&#xff1a; 数据源的TiDB学习之路 原文来源&#xff1a; https://tidb.net/blog/d052ee0b 2024 年 9 月 30 日&#xff0c;中国信息安全测评中心公布安全可靠测评结果公告&#xff08;2024年第2号&#xff09;&#xff0c;其中包含 6 款集中式数据库和 11 款分布式数据…

鸿蒙网络编程系列30-断点续传下载文件示例

1. 断点续传简介 在文件的下载中&#xff0c;特别是大文件的下载中&#xff0c;可能会出现各种原因导致的下载暂停情况&#xff0c;如果不做特殊处理&#xff0c;下次还需要从头开始下载&#xff0c;既浪费了时间&#xff0c;又浪费了流量。不过&#xff0c;HTTP协议通过Range…

信息安全工程师(58)网络安全漏洞处置技术与应用

前言 网络安全漏洞处置技术与应用是一个复杂而关键的领域&#xff0c;它涉及漏洞的发现、评估、修补以及后续的监控与防范等多个环节。 一、网络安全漏洞发现技术 网络安全漏洞发现技术是漏洞处置的首要步骤&#xff0c;它旨在通过各种手段识别出网络系统中存在的潜在漏洞。这些…

jupyter notebook远程连接服务器

jupyter notebook远程连接服务器 文章目录 jupyter notebook远程连接服务器jupyter是什么配置步骤安装jupyter生成jupyter配置文件编辑jupyter配置文件设置密码ssh隧道 启动顺序jupyter添加kernel下载ipykernel包添加kernel 测试遇到的问题 jupyter是什么 Jupyter Notebook是一…

数据结构之队列(python)

华子目录 1.队列存储结构1.1队列基本介绍1.2队列的实现方式 2.顺序队列2.1顺序队列的介绍2.2顺序队列的简单实现2.3代码实现 3.链式队列和基本操作3.1链式队列数据入队3.2链式队列数据出队3.3队列的链式表示和实现 1.队列存储结构 1.1队列基本介绍 队列的两端都"开口&qu…

FFmpeg 4.3 音视频-多路H265监控录放C++开发三 :安装QT5.14.2, 并将QT集成 到 VS2019中。

一&#xff0c;安装QT&#xff0c; 重点&#xff1a;在安装QT的时候要安装msvc201x版本的组件&#xff0c; 二 &#xff0c; 安装 qt-vs-tools Index of /development_releases/vsaddin/2.8.1 三&#xff0c;需要安装过 windows10 SDK&#xff0c;一般我们在安装vs2019的时候就…

餐饮店怎么标注地图位置信息?

随着市场竞争的日益激烈&#xff0c;商家若想在竞争中脱颖而出&#xff0c;就必须想方设法去提高自身的曝光度和知名度&#xff0c;为店铺带来更多的客流量。其中&#xff0c;地图标注便是一种简单却极为有效的方法。通过在地图平台上添加店铺位置信息&#xff0c;不仅可以方便…

电子级异丙醇溶液除硼树脂

电子级异丙醇溶液的净化除杂是一个精细的过程&#xff0c;旨在去除溶液中的杂质&#xff0c;以满足电子行业对高纯度化学品的严格要求。以下是电子级异丙醇溶液净化除杂的相关信息&#xff1a; 净化除杂方法 ● 精馏工序&#xff1a;通过精馏塔进行初步分离&#xff0c;去除大部…

(44)MATLAB读取语音信号进行频谱分析

文章目录 前言一、MATLAB代码二、仿真结果画图三、频谱分析 前言 语音信号是我们最常见的一种信号&#xff0c;本文使用MATLAB读取一段语音信号画出其波形&#xff0c;然后使用FFT变换给出其频谱&#xff0c;对其频谱进行分析。 一、MATLAB代码 读取语音数据并得出频谱的代码…

JMeter如何设置HTTP代理服务器?

1、 2、添加线程组 3、设置HTTP代理服务器&#xff0c;目标控制器选择“测试计划>线程组” 过滤掉不需要的信息 4、设置电脑手动代理 5、点击启动&#xff0c;在浏览器操作就可以了

Halcon实战——基于NCC模板匹配的芯片检测(附源码)

Halcon实战——基于NCC模板匹配的芯片检测&#xff08;附源码&#xff09; 关于作者 作者&#xff1a;小白熊 作者简介&#xff1a;精通python、matlab、c#语言&#xff0c;擅长机器学习&#xff0c;深度学习&#xff0c;机器视觉&#xff0c;目标检测&#xff0c;图像分类&am…

OpenCV高级图形用户界面(10)创建一个新的窗口函数namedWindow()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 创建一个窗口。 函数 namedWindow 创建一个可以作为图像和跟踪条占位符的窗口。创建的窗口通过它们的名字来引用。 如果已经存在同名的窗口&am…

应用层协议 序列化

自定义应用层协议 例子&#xff1a;网络版本计算器 序列化反序列化 序列化&#xff1a;将消息&#xff0c;昵称&#xff0c;日期整合成消息-昵称-日期 反序列化&#xff1a;消息-昵称-日期->消息&#xff0c;昵称&#xff0c;日期 在序列化中&#xff0c;定义一个结构体…

第8篇:网络安全基础

目录 引言 8.1 网络安全的基本概念 8.2 网络威胁与攻击类型 8.3 密码学的基本思想与加密算法 8.4 消息认证与数字签名 8.5 网络安全技术与协议 8.6 总结 第8篇&#xff1a;网络安全基础 引言 在现代信息社会中&#xff0c;计算机网络无处不在&#xff0c;从互联网到局…

C语言_指针_进阶

引言&#xff1a;在前面的c语言_指针初阶上&#xff0c;我们了解了简单的指针类型以及使用&#xff0c;下面我们将进入更深层次的指针学习&#xff0c;对指针的理解会有一个极大的提升。从此以后&#xff0c;指针将不再是难点&#xff0c;而是学习底层语言的一把利器。 本章重点…

Mysql(2)—SQL语法详解(通俗易懂)

一、关于SQL 1.1 简介 SQL&#xff08;Structured Query Language&#xff0c;结构化查询语言&#xff09;是一种用于管理关系型数据库的标准编程语言。它主要用于数据的查询、插入、更新和删除等操作。SQL最初在1970年代由IBM的研究人员开发&#xff0c;旨在处理关系数据模型…

API的力量:解决编程技术问题的利器

在软件开发的世界里&#xff0c;编程技术问题无处不在。从数据获取到用户认证&#xff0c;从支付处理到地图服务&#xff0c;这些问题的解决方案往往需要深厚的专业知识和大量的开发时间。然而&#xff0c;应用程序编程接口&#xff08;API&#xff09;的出现&#xff0c;为开发…

长序列时间序列预测模型:Informer与TimesNet

Informer超越长序列时间序列预测 Informer是一种针对长序列时间序列预测的高效Transformer模型&#xff0c;旨在解决传统Transformer在处理长序列时的局限性。该模型引入了一些关键技术&#xff0c;以提高效率和准确性。以下是对Informer模型的详细介绍&#xff1a; 1. 模型背…