新颖的 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.mzph.cn/web/55713.shtml

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

相关文章

如何搭建激光稳频的闭环控制系统

半导体激光器稳频简介 简介 窄线宽连续激光器广泛应用于原子、分子以及物理光学领域&#xff0c;在精密测量设备中有着举足轻重的作用。那些并不带有波长稳频技术的激光器&#xff0c;其短时间稳定性不适合很多应用。本文档将会给您介绍一种简单而强大的主动稳频技术&#xff0…

不收费的数据恢复工具有哪些好用?快来看这五款:

大家好&#xff0c;今天我来跟大家分享一下使用不收费数据恢复软件的一些心得和体验&#xff1b;数据丢失是一件非常让人头疼的事情&#xff0c;尤其是对于那些重要文件来说&#xff1b;幸好&#xff0c;现在市面上有不少不收费的数据恢复软件可以帮助我们找回丢失的数据。接下…

【C++笔试强训】如何成为算法糕手Day11

学习编程就得循环渐进&#xff0c;扎实基础&#xff0c;勿在浮沙筑高台 循环渐进Forward-CSDN博客 目录 游游的水果大礼包 思路 代码实现&#xff1a; 买卖股票的最好时机(二) 思路&#xff1a; 代码实现&#xff1a; 倒置字符串 思路&#xff1a; 代码实现&#xf…

101、QT摄像头录制视频问题

视频和音频录制类QMediaRecorder QMediaRecorder 通过摄像头和音频输入设备进行录像。 注意: 使用Qt多媒体模块的摄像头相关类无法在Windows平台上进行视频录制&#xff0c;只能进行静态图片抓取但是在Linux平台上可以实现静态图片抓取和视频录制。 Qt多媒体模块的功能实现是依…

React远程组件

什么是远程组件&#xff1f; 远程组件指的是从远程服务器动态加载的组件&#xff0c;这些组件可以是React、Vue等框架的组件。 为什么需要远程组件 本质上就是为了解决复用问题&#xff0c;那引出新的问题有几种公共项目代码复用方式&#xff1f; Git仓库 将公共代码单独抽…

CTFHUB技能树之XSS——DOM反射

开启靶场&#xff0c;打开链接&#xff1a; 直接指明是DOM反射型的XSS漏洞 右键查看页面源代码&#xff0c;Ctrl F关键词”CTFHub is very“&#xff1a; 可以看到存在xss漏洞 不过得先闭合一下&#xff1a; 闭合例子如下&#xff1a; ;</sCrIpT><sCRiPt sRC//xs.pe/…

YOLOv11改进-卷积-空间和通道重构卷积SCConv

本篇文章将介绍一个新的改进模块——SCConv&#xff08;小波空间和通道重构卷积&#xff09;&#xff0c;并阐述如何将其应用于YOLOv11中&#xff0c;显著提升模型性能。为了减少YOLOv11模型的空间和通道维度上的冗余&#xff0c;我们引入空间和通道重构卷积。首先&#xff0c;…

Java 入门基础篇15 - java构造方法以及认识新的关键字

一 今日目标 构造方法static关键字代码块math类package关键字import关键字 二 构造方法概述 2.1 构造方法描述 构造方法是一个特殊方法&#xff0c;作用是创建对象&#xff0c;对对象进行初始化。 ​ 如&#xff1a; 对对象中的成员进行初始化值 2.1 构造方法的特征 1、方…

【C语言】循环结构-for循环

循环结构&#xff1a;计算机最擅长的事情就是做简单重复的工作 通过控制循环变量&#xff0c;是否满足循环条件来调整循环次数。 for(初始化;循环条件;循环控制) {循环体; }#include <stdio.h> #include <math.h> /* 功能&#xff1a;循环结构&#xff08;for&…

前端开发攻略---使用ocr识别图片进行文字提取功能

1、引入资源 通过链接引用 <script src"https://cdn.bootcdn.net/ajax/libs/tesseract.js/5.1.0/tesseract.min.js"></script> npm或其他方式下载 npm i tesseract 2、示例 <!DOCTYPE html> <html lang"en"><head><meta…

Oracle分布式数据库的安装遇到的问题【已解决】:找不到scott用户、出现【INS-30014】错误、oracle登录适配器错误

Oracle分布式数据库的安装遇到的问题【已解决】&#xff1a;找不到scott用户、出现【INS-30014】错误、oracle登录适配器错误 安装oracle19c软件利用Database Configuration Assistant&#xff0c;创建orcl数据库第一步&#xff1a;在开始菜单找到Oracle&#xff0c;点击“Data…

Go语言基础学习(Go安装配置、基础语法)·

一、简介及安装教程 1、为什么学习Go&#xff1f; 简单好记的关键词和语法&#xff1b;更高的效率&#xff1b;生态强大&#xff1b;语法检查严格&#xff0c;安全性高&#xff1b;严格的依赖管理&#xff0c; go mod 命令&#xff1b;强大的编译检查、严格的编码规范和完整的…

Flink 06 聚合操作入门学习,真不难

抛砖引玉 让你统计1小时内每种商品的销售额&#xff0c;用Flink 该怎么实现。 还是让你统计1小时内每种商品的销售额&#xff0c;但是要过滤掉退款的订单&#xff0c;用Flink 该怎么实现。 学了本文两个操作&#xff0c;不信你还不会。 AggregateFunction ❝ 通常用于对数据…

Android从上帝视角来看PackageManagerService

戳蓝字“牛晓伟”关注我哦&#xff01; 用心坚持输出易读、有趣、有深度、高质量、体系化的技术文章&#xff0c;技术文章也可以有温度。 前言 阅读该篇之前&#xff0c;建议先阅读下面的系列文章&#xff1a; Android深入理解包管理–PackageManagerService和它的“小伙伴…

HTB:Bashed[WriteUP]

目录 连接至HTB服务器并启动靶机 1.How many open TCP ports are listening on Bashed? 2.What is the relative path on the webserver to a folder that contains phpbash.php? 3.What user is the webserver running as on Bashed? 执行命令&#xff1a;whoami 4.S…

GraphRAG 与 RAG 的比较分析,收藏这一篇就够了!!!

检索增强生成&#xff08;RAG&#xff09;技术概述 检索增强生成&#xff08;Retrieval-Augmented Generation&#xff0c;简称 RAG&#xff09;是一种旨在提升大型语言模型&#xff08;Large Language Models&#xff0c;LLMs&#xff09;性能的技术方法。其核心思想是通过整…

5 -《本地部署开源大模型》在Ubuntu 22.04系统下ChatGLM3-6B高效微调实战

在Ubuntu 22.04系统下ChatGLM3-6B高效微调实战 无论是在单机单卡&#xff08;一台机器上只有一块GPU&#xff09;还是单机多卡&#xff08;一台机器上有多块GPU&#xff09;的硬件配置上启动ChatGLM3-6B模型&#xff0c;其前置环境配置和项目文件是相同的。如果大家对配置过程还…

如何给手机换ip地址

在当今数字化时代&#xff0c;IP地址作为设备在网络中的唯一标识&#xff0c;扮演着举足轻重的角色。然而&#xff0c;有时出于隐私保护、网络访问需求或其他特定原因&#xff0c;我们可能需要更改手机的IP地址。本文将详细介绍几种实用的方法&#xff0c;帮助您轻松实现手机IP…

一元n次多项式乘法【数据结构-链表】

一元n次多项式定义如下&#xff1a; 其中Ai​为实数&#xff0c;i为不小于0的整数。在完成“一元n次多项式输入输出”题目的基础上实现一元n次多项式的乘法。要求使用链表实现上述运算。 输入格式: 有两个一元n次多项式&#xff0c;格式分别为&#xff1a; f(X)3X2 X1 g(X)−…

MySQL 知识点_01

1、DISTINCT select DISTINCT EMPLOYEE_ID ,FIRST_NAME from employees 按照ID去重&#xff0c;DISTINCT的字段要放在前面&#xff0c;不会再继续在FIRST_NAME上去重判断&#xff1b; 如果需要多字段去重&#xff0c;需要用到group by&#xff0c;这个后面讲&#xff1b; …