【每日一面】setTimeout 延时为 0 的情况

news/2025/9/29 10:19:06/文章来源:https://www.cnblogs.com/keepsmart/p/19118235

基础问答

问题:你在写代码的过程中,在什么时候才会设置 setTimeout 的延时为 0?

回答:有如下几种情况

  1. 避免同步任务阻塞 UI,即在渲染较多数据的时候,可以通过 setTimeout 分批渲染。
const data = new Array(1000).fill(1).map((x, idx) => idx + 1);function render(list) {let index = 0;for (; index < list.length; index += 100) {console.log('current', index);const current = index;setTimeout(() => { console.log(list.slice(current, current + 100).join(','))}, 0);}
}render(data);
  1. 获取 DOM 元素的宽高,本质是根据事件循环机制调整了代码的执行顺序。
function App() {const dom = document.querySelector('#app');console.log(dom.height);setTimeout(() => dom.height, 0);
}
  1. 代码分片,古早技术,将同步代码分片执行,避免阻塞渲染。

扩展延伸

JavaScript 单线程:JavaScript 是单线程语言,这个是编程语言的设计,在同一时间只能执行一段代码,所有的任务都需要排队,而身为单线程,但是好像我们访问网页的时候还是那么快,这语言优势这么强?这是另一个问题,语言设计上是单线程,只能同步的执行代码,但是浏览器不是,他是多线程的,分出来一个 JS 主线程用于执行 JavaScript 代码,还有如 UI 线程,用于执行渲染等。在 JavaScript 中,通过事件循环来协调任务执行,实现异步编程。

事件循环:这个机制是 JavaScript 的一个核心机制,可以利用这个机制实现高并发,异步编程操作。

核心是 - 调用栈、任务队列、宏任务、微任务

整个流程为 - JavaScript 代码按照代码依次执行时,检测到同步任务就进入调用栈执行,检测到宏任务,先压入宏任务队列,检测到微任务,则压入微任务队列,当本轮同步任务(宏任务)结束时,检测微任务队列,清空(即执行所有的微任务),这个检测的时机称为“微任务检查点”。

yuque_diagram (1)

如图,伴随着每个宏任务执行,都有自己对应的微任务队列,直到微任务队列全部执行完成,才会开启下一个宏任务。

setTimeout(callback, delayTime) API:在执行这个 API 时,JS 引擎会将 callback 函数封装成宏任务,挂载到延迟队列中,等待执行。这里再次引入了一个新的概念,延迟队列,这个是浏览器(或者引擎)实现的,当 JavaScript 创建定时器的时候,渲染进程就会将这个定时器的任务添加到延迟队列中。执行完一个任务,计算延迟队列中是否有到期的任务,有就执行,没有继续循环。

面试追问

  1. 延迟时间为 0,会立即执行吗?

不会,虽然我们设置为了 0,但是 setTimeout 的回调函数会被封装成一个宏任务,所以他需要等待同步任务执行结束后,从宏任务队列中取出来执行。此外,这个延迟时间虽然可以设置为 0,但是浏览器的最小执行时间实际是不一定的,Chrome 浏览器是 4ms。

  1. 那延迟时间设置为 400ms,会在 400ms 时执行吗?

不会,原因同上。setTimeout 只能做到“尽快执行”,而不是“立即执行”。

  1. 你在使用 setTimeout 的时候,有遇到过什么问题吗?

历史代码问题,存在比较多的 setTimeout 导致代码执行的结果不好理解。

this 指针问题,setTimeout 回调函数中的 this 和直觉不符,如果执行的回调函数是一个对象的方法,那么这个对象的方法中 this 并不是指向这个对象,而是全局。

长任务阻塞延迟的回调函数调用,如果当前任务执行的时间比较长,可能会导致回调函数等待。

浏览器优化问题,现在浏览器为了降低对电量的消耗,延长续航时间,会对后台界面的 setTimeout 执行时间间隔延长,一般会大于 1s,但是遇到过更久的,有一个多小时。

  1. 那有没有可以替代的 API?

有,和动画相关的可以使用 requestAnimationFrame API 来替代,可以保持和浏览器渲染频率一致,而不需要计算每帧的间隔时间来延迟执行。

微任务可以使用 Promise 来创建。

  1. 实现一个简单的 setTimeout。
/*** 用 requestAnimationFrame 实现简易 setTimeout* @param {number} delay - 延迟时间(毫秒)* @returns {number} - RAF的ID,用于取消(对应clearTimeout)*/​
function rafSetTimeout(callback, delay) {// 1. 记录延迟结束的目标时间(当前时间 + 延迟时间)const startTime = Date.now();const targetTime = startTime + delay;// 2. 定义递归执行的RAF回调函数function rafCallback() {// 3. 检查当前时间是否达到目标时间if (Date.now() >= targetTime) {// 达到目标时间,执行用户回调callback();} else {// 未达到,继续递归调用RAF,等待下一次重绘requestAnimationFrame(rafCallback);}}// 4. 启动第一次RAF,开始等待return requestAnimationFrame(rafCallback);
}/*** 对应 clearTimeout,取消 rafSetTimeout* @param {number} rafId - rafSetTimeout 返回的RAF ID*/
function rafClearTimeout(rafId) {cancelAnimationFrame(rafId);
}
  1. 经典题目,判断运行结果,这里给个简单的例子。
setTimeout(() => {console.log('回调1');
}, 0);// 插入同步任务
console.log('同步任务');setTimeout(() => {console.log('回调2');
}, 0);

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

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

相关文章

honeywell扫码枪设置

honeywell扫码枪设置1.2.如何使用Tera Term发送十六进制数给扫码枪? 使用 Tera Term 宏(TTL 脚本)如果你需要发送重复的或更复杂的十六进制序列,或者需要处理大于 0x7F 的字节(在某些字符集设置下可能会有问题),…

Python3 pip 详解

Python3 pip 详解pip 是 Python 生态中最核心的包管理工具,用于安装、升级、卸载第三方 Python 库,是 Python 开发者日常工作中不可或缺的工具。本文将从基础概念到高级用法,全面解析 pip 在 Python3 环境下的使用方…

IP5306 测试

IP5326使用测试测试 1 (寄存器控制)在进入 I2C 模式前会进行检测,需要引脚首先是高电平才行。如果电源与MCU的 上电不能同步,将不会进入I2C 模式。I2C 读取充电状态,充电进行状态并不是总是正常,好在其他状态也会…

AI元人文:悟空博弈框架

AI元人文:悟空博弈框架 文/岐金兰AI元人文:悟空博弈框架 ——基于三值模型与价值原语的人机协同决策体系命名释义「悟空」勘破表象:借AI之力洞见价值冲突的本质,超越人类认知局限;悬荡空明:在计算与人文的临…

phpcms网站打不开苏州做网站费用明细

图像识别是计算机视觉领域的一个重要分支&#xff0c;它的基本任务是从图像中提取出有助于分类或识别的信息&#xff0c;这些信息通常称为“特征”。特征提取是图像识别中的关键技术之一&#xff0c;它决定了识别系统性能的好坏。以下是几种常见的特征提取技术&#xff1a; 边…

sway - wayland下截图方案

bindsym Ctrl+Alt+q exec grim -g "$(slurp)" - | wl-copy && wl-paste > /tmp/screan_snapshot_file && swappy -f /tmp/screan_snapshot_filewl-copy 获图片字节 wl-paste 将图片字节写…

不同网络间文件互传怎么实现?

不同网络间文件互传怎么实现的需求,常出现在企业内网与外网、涉密网与非涉密网间的数据交换场景中。传统方法如人工拷贝、云盘同步等,存在数据泄露、合规性缺失及操作繁琐等问题。而“Ftrans Ferry跨网文件安全交换系…

实用指南:Qt容器QList、QLinkedList、QVector特性浅谈

实用指南:Qt容器QList、QLinkedList、QVector特性浅谈2025-09-29 10:03 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; d…

模板网站建设推广大埔县住房城乡规划建设局网站

文章目录1.什么是static&#xff1f;2.static关键字的作用是什么&#xff1f;3.静态变量和非静态变量的区别&#xff1f;4.static可以修饰局部变量吗&#xff1f;5.可以通过this访问静态变量吗&#xff1f;6.静态方法能否调用非静态方法&#xff1f;7.静态变量、普通变量、静态…

sway wayland下 wps-office无法输入中文

alias wps="LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8 XMODIFIERS="@im=fcitx" GTK_IM_MODULE="fcitx" QT_IM_MODULE="fcitx" SDL_IM_MODULE=fcitx GLFW_IM_MODULE=ibus wps"

科学史笔记

2025.9.29 人工智能法,机器学习史。

Spring XML 设置简介

Spring XML 设置简介pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "…

2025 年真空泵品牌最新权威推荐排行榜:覆盖真空泵维修,真空泵机组,真空泵油,真空泵配件领域选择指南

当前工业领域中,真空泵作为太阳能、真空镀膜、电子电路板等行业的核心设备,其品质与服务直接关乎企业生产效率与成本控制。但随着市场需求激增,大量品牌涌入导致市场鱼龙混杂,部分产品存在抽气效率低、运行不稳定、…

专业的跨网文件交换系统 和传统FTP/U盘拷贝有什么区别?

跨网文件交换系统是用来专门解决跨隔离网络文件交换问题的,传统的FTP、U盘,以及网闸自带的摆渡功能等,其实严格意义上来说,并不能算是跨网文件交换系统,只能算是一种跨网传输方式。这些传统的方式,如今已经或多或…

Group Theory Note

Laws of Composition Def. (Laws of Composition) any rule combining pairs of element of S to get another element of S: #S\times S \to S#. Def. (Associative law) Skipped Prop. 2.1.4 (Associative law #\Lef…

InnoDB ReplicaSet和其他数据库高可用方案有什么区别?

InnoDB ReplicaSet和其他数据库高可用方案有什么区别?要理解 InnoDB ReplicaSet 与其他数据库高可用方案的区别,需先明确其核心定位:它是 MySQL 原生轻量级高可用方案,基于 GTID(全局事务标识符)设计,聚焦 “简…

CF *2600 思维题 2

CF *2600 思维题 2 A CF1819D Misha and Apples \(\text{Link}\)之前做过的原题,现在还能想起来。考虑我们最后取得一定是一段后缀,那么我们想让这个后缀尽可能的长。我们从左往右遍历 \(i\),并维护指针 \(p\) 表示…

中低压配网设备介绍

一、网络结构形式1、树状结构(放射式):形式简单,但没有转供电能力,只能通过分段开关、支线开关来缩小停电范围:2、环网结线:形式相对树状结构复杂,具备转供电能力,环网结线有以下几种方式:(1)典型结线,转供电能力…

设计教程网站推荐湖南网络推广排名

所用环境 宝塔云服务器 log4j2 是Apache的⼀个java日志框架&#xff0c;我们借助它进行日志相关操作管理&#xff0c;然而在2021年末log4j2爆出了远程代码执行漏洞&#xff0c;属于严重等级的漏洞。 apache log4j通过定义每⼀条日志信息的级别能够更加细致地控制日志⽣成地过…