当前位置: 首页 > news >正文

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

基础问答

问题:你在写代码的过程中,在什么时候才会设置 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.sczhlp.com/news/147322/

相关文章:

  • 漳州平台网站建设重庆重庆网站建设
  • 南京网站设计哪家公司好做视频付费网站
  • 网站开发部网站建设在阿里云
  • wordpress 图片站模板寿光做网站的公司
  • 怎么做示爱的网站中国关键词
  • 建设部网站安全考核证书查询专门做杂志的网站有哪些
  • 网站模板怎么修改成可视化dedecms医院网站wap模板(橙色)
  • 长尾关键词挖掘网站微信公众号开发平台登录
  • AI元人文:悟空博弈框架
  • 网站seo诊断分析和优化方案网络运维前景怎么样
  • 网站主题分析有没有兼职做设计的网站吗
  • 北京网站设计公司飞沐seo先上排名后收费
  • 计算机网络技术专业主要学什么东莞整站优化
  • 公司网站是别人做的如何换logo如何提高网站的用户体验ue
  • 南阳企业做网站wordpress外国主题
  • 向公司申请请做网站山东城乡和住房建设厅官网
  • 包头哪有做网站的wordpress延迟加载
  • 平面设计资料网站震泽做网站
  • 做视频网站服务器要求在那个网站做定制旅游
  • 网站建设的流程及步骤贵阳专业网站建设公司
  • sway wayland下 wps-office无法输入中文
  • 科学史笔记
  • 好网站建设水务局政务网站建设工作总结
  • 国外做网站的公司wordpress 初始化 数据库连接
  • 安徽建设厅网站打不开phpwind的代表网站
  • 毕设做网站些什么比较简单新浪网页版
  • 同一个服务器的网站做友情链接怎样自己创造网站
  • Spring XML 设置简介
  • 2025 年真空泵品牌最新权威推荐排行榜:覆盖真空泵维修,真空泵机组,真空泵油,真空泵配件领域选择指南
  • 专业的跨网文件交换系统 和传统FTP/U盘拷贝有什么区别?