再谈谈 Promise, setTimeout, rAF, rIC

栏目: JavaScript · 发布时间: 5年前

内容简介:欢迎关注我的公众号

欢迎关注我的公众号 睿Talk ,获取我最新的文章:

再谈谈 Promise, setTimeout, rAF, rIC

一、前言

Promise , setTimeout , requestAnimationFrame , requestIdleCallback 这几个概念相信很多人都很熟悉了,最近在看 React Fiber 源码的时候又对它们有了更深一层的认识,在此分享一下。下文将用 rAF 代表 requestAnimationFrame , rIC 代表 requestIdleCallback

二、事件循环与帧

事件循环和上面 4 个名词的基本概念在此不再啰嗦了,我们着重看下它们之间的关系。浏览器是一个 UI 系统,所有的操作最终都会以页面的形式展现,而页面的基本单位是帧。一帧中可能包括的任务有下面几种类型。

再谈谈 Promise, setTimeout, rAF, rIC

setTimeout
Promise
requestAnimationFrame
requestIdleCallback

理想情况下,页面会以 60 帧每秒的帧率来运行,但实际上每秒绘制多少帧是由多个因素决定的,下面举一些例子:

rAF

从上面的例子可以看出,页面的帧率不是固定的,是会动态变化的。比如某一帧中的任务占据大量时间的情况下,会影响到下一帧的执行。那么谁来调节帧率呢?显然只能依靠浏览器自身。作为开发者的我们是无法准确知道回调什么时候执行的。比如:

function animation() {
   console.log('time: ', +new Date());
   setTimeout(animate, 1000 / 60);
}

animation();

上面的函数是假定浏览器以帧率 60 运行的,当帧率达不到的时候,2 帧之间回调可能执行了多次,也可能一次都不执行,简称掉帧。

所以在制作动画的时候,我们不能预设浏览器的帧率,正确的做法是通过 rAF 注册回调, 由浏览器来控制动画调用时机:

function animation() {
   console.log('time: ', +new Date());
   requestAnimationFrame(animation);
}

animation();

rAF 会保证注册的回调会在下次渲染页面之前执行,且只会执行一次。当页面处于不可见状态时, rAF 会自动停止执行,以节省系统资源。

三、执行顺序

Promise , setTimeout , rAFrIC 对应 4 种队列:微任务队列、宏任务队列、animation 队列和 idle 队列。

  • 微任务队列会在 JS 运行栈为空的时候立即执行。
  • animation 队列会在页面渲染前执行。
  • 宏任务队列优先级相对较低。
  • idle 队列优先级最低,当浏览器有空闲时间的时候才会执行。
setTimeout(()=>console.log('setTimeout'), 0);
Promise.resolve().then(()=>console.log('promise'));
requestAnimationFrame(()=>console.log('animation'));
requestIdleCallback(()=>console.log('idle'));

// 执行结果: promise, animation, setTimeout, idle

再来谈谈空闲时间怎么理解。假设在 1 秒内有 3 帧需要渲染:

再谈谈 Promise, setTimeout, rAF, rIC

rAF

rAF 类似, rIC 的执行时机是由浏览器控制的,能更好的保证体验,优化性能。一般高优先级的任务(如 UI 更新)会放在 rAF 队列,低优先级任务(如日志上传)会放 rIC

四、队列特性

在一个事件循环内,各个队列有以下特性:

  • 宏任务队列,每次只会执行队列内的一个任务。
  • 微任务队列,每次会执行队列里的全部任务。假设微任务队列内有 100 个 Promise,它们会一次过全部执行完。这种情况下极有可能会导致页面卡顿。如果在微任务执行过程中继续往微任务队列中添加任务,新添加的任务也会在当前事件循环中执行,很容易造成死循环, 如:
function loop() {
    Promise.resolve().then(loop);
}

loop();
React Fiber

五、总结

本文介绍了 4 种队列的执行顺序和每个队列的特性,它们是:宏任务队列、微任务队列、animation 队列和 idle 队列。实际应用时可以根据它们各自的特点分配不同的任务。


以上所述就是小编给大家介绍的《再谈谈 Promise, setTimeout, rAF, rIC》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

JSP 2.0技术手册

JSP 2.0技术手册

杜远君、林康司、林上杰 / 湖北教育出版社,电子工业出版社 / 2004-5-1 / 59.0

本书图文并茂,以丰富的实例为引导,全面介绍了主流的Java Web开发技术——JSP 2.0,重点介绍Java在展示层的两项重要技术:Java Servlet与JavaServer Pages。它们是最重要的Java核心技术。对这两项技术的深入了解,将有助于您未来对于JavaServer Faces(JSF)技术以及Java Web Services技术的学习。 本书分为三大部分,前......一起来看看 《JSP 2.0技术手册》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

URL 编码/解码
URL 编码/解码

URL 编码/解码