news 2026/4/3 1:33:28

】setTimeout 延时为 0 的情况

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
】setTimeout 延时为 0 的情况

基础问答

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

回答:有如下几种情况

避免同步任务阻塞 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);

获取 DOM 元素的宽高,本质是根据事件循环机制调整了代码的执行顺序。

function App() {

const dom = document.querySelector('#app');

console.log(dom.height);

setTimeout(() => dom.height, 0);

}

代码分片,古早技术,将同步代码分片执行,避免阻塞渲染。

扩展延伸

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

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

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

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

yuque_diagram (1)

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

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

面试追问

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

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

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

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

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

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

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

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

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

那有没有可以替代的 API?

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

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

实现一个简单的 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);

}

经典题目,判断运行结果,这里给个简单的例子。

setTimeout(() => {

console.log('回调1');

}, 0);

// 插入同步任务

console.log('同步任务');

setTimeout(() => {

console.log('回调2');

}, 0);

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/2 12:38:05

基于Spring Boot的实验室设备管理系统

基于Spring Boot的实验室设备管理系统的介绍 一、系统背景与目标 实验室设备管理是高校、科研机构及企业研发部门的核心工作之一。传统设备管理依赖人工记录和纸质文档&#xff0c;存在信息滞后、设备利用率低、维护不及时等问题。本系统基于Spring Boot框架与Java技术栈开发&a…

作者头像 李华
网站建设 2026/3/30 5:26:47

一个纯净的自动微分框架—autograd

技术背景自动微分是一个在深度学习等计算领域非常常用的一个工具了&#xff0c;其核心原理就是基于链式法则的求导。但是如果只是为了使用一个自动微分的功能&#xff0c;不做深度学习的话&#xff0c;去安装一个庞大的深度学习框架&#xff0c;学习成本是很高的&#xff0c;尤…

作者头像 李华
网站建设 2026/4/3 1:32:11

考研调剂经验分享

个人简介一志愿西南交通大学&#xff0c;专业代码120100&#xff0c;总分366分&#xff08;数学三88分&#xff0c;英语一77分&#xff0c;政治70分&#xff0c;运筹学131分&#xff09;。选择了三所调剂院校&#xff0c;被浙江理工大学拒绝&#xff0c;我拒绝了北京信息科技大…

作者头像 李华
网站建设 2026/4/1 1:20:12

多平台广告联盟APP开发:iOS/Android 双端适配与跨平台数据互通方案

在广告联盟 APP 的商业化落地中&#xff0c;iOS/Android 双端覆盖是触达全量用户的基础&#xff0c;而跨平台数据互通则是实现流量分层定价、广告精准匹配、收益统一结算的核心。但双端开发存在 “系统差异大、适配成本高” 的痛点&#xff0c;跨平台数据同步则面临 “数据格式…

作者头像 李华
网站建设 2026/3/29 23:18:39

Linux系统编程——线程控制

目录 一、临界资源与线程安全问题 二、互斥&#xff1a;让临界区 “独占” 执行 1.互斥锁的原理 2.互斥锁的使用步骤&#xff08;pthread 库&#xff09; 2.1 定义互斥锁 2.2 初始化互斥锁 2.3 加锁&#xff08;进入临界区&#xff09; 2.4 解锁&#xff08;离开临界区…

作者头像 李华