页面流畅与 FPS

页面是一帧一帧绘制出来的,当每秒绘制的帧数(FPS)达到 60 时,页面是流畅的,小于这个值时,用户会感觉到卡顿。

1s 60帧,所以每一帧分到的时间是 1000/60 ≈ 16 ms。所以我们书写代码时力求不让一帧的工作量超过 16ms。

Frame

那么浏览器每一帧都需要完成哪些工作?



浏览器一帧内的工作

通过上图可看到,一帧内需要完成如下六个步骤的任务:

  • 处理用户的交互
  • JS 解析执行
  • 帧开始。窗口尺寸变更,页面滚去等的处理
  • rAF
  • 布局
  • 绘制

requestIdleCallback

上面六个步骤完成后没超过 16 ms,说明时间有富余,此时就会执行 requestIdleCallback 里注册的任务。



requestIdleCallback 在浏览器一帧内的位置示意

从上图也可看出,和 requestAnimationFrame 每一帧必定会执行不同,requestIdleCallback 是捡浏览器空闲来执行任务。

如此一来,假如浏览器一直处于非常忙碌的状态,requestIdleCallback 注册的任务有可能永远不会执行。此时可通过设置 timeout (见下面 API 介绍)来保证执行。

API

var handle = window.requestIdleCallback(callback[, options])
  • callback: ():回调即空闲时需要执行的任务,接收一个 IdleDeadline 对象作为入参。其中 IdleDeadline 对象包含:

    • didTimeout,布尔值,表示任务是否超时,结合 timeRemaining 使用。
    • timeRemaining(),表示当前帧剩余的时间,也可理解为留给任务的时间还有多少。
  • options:目前 options 只有一个参数
    • timeout 。表示超过这个时间后,如果任务还没执行,则强制执行,不必等待空闲。

示例

requestIdleCallback(myNonEssentialWork, { timeout: 2000 });

function myNonEssentialWork (deadline) {

  // 如果帧内有富余的时间,或者超时

  while ((deadline.timeRemaining() > 0 || deadline.didTimeout) &&

         tasks.length > 0)

    doWorkIfNeeded();   if (tasks.length > 0)

    requestIdleCallback(myNonEssentialWork);

}

超时的情况,其实就是浏览器很忙,没有空闲时间,此时会等待指定的 timeout 那么久再执行,通过入参 dealine 拿到的 didTmieout 会为 true,同时 timeRemaining () 返回的也是 0。超时的情况下如果选择继续执行的话,肯定会出现卡顿的,因为必然会将一帧的时间拉长。

cancelIdleCallback

setTimeout 类似,返回一个唯一 id,可通过 cancelIdleCallback 来取消任务。

总结

一些低优先级的任务可使用 requestIdleCallback 等浏览器不忙的时候来执行,同时因为时间有限,它所执行的任务应该尽量是能够量化,细分的微任务(micro task)。

因为它发生在一帧的最后,此时页面布局已经完成,所以不建议在 requestIdleCallback 里再操作 DOM,这样会导致页面再次重绘。DOM 操作建议在 rAF 中进行。同时,操作 DOM 所需要的耗时是不确定的,因为会导致重新计算布局和视图的绘制,所以这类操作不具备可预测性。

Promise 也不建议在这里面进行,因为 Promise 的回调属性 Event loop 中优先级较高的一种微任务,会在 requestIdleCallback 结束时立即执行,不管此时是否还有富余的时间,这样有很大可能会让一帧超过 16 ms。

参考

利用好浏览器的空闲时间 --- requestIdleCallback的更多相关文章

  1. 移动WebApp利用Chrome浏览器进行调试

    详细的请看这个(HBuilder是我长期使用,而且值得支持的国内前端开发编辑器) http://ask.dcloud.net.cn/article/151 http://ask.dcloud.net. ...

  2. 系统空闲时间判断&命名验证

    一.系统空闲时间判断 需要一个自动登录注销的功能,当鼠标移动和或者键盘输入的时候认为当前用户在线,否则过了设置时间就自动退出.好在前辈们留下了这样的一个类: MouseKeyBoardOperate: ...

  3. mysql连接的空闲时间超过8小时后 MySQL自动断开该连接解决方案

    在连接字符串中  添加设置节点 ConnectionLifeTime(计量单位为 秒).超过设定的连接会话 会被杀死! Connection Lifetime, ConnectionLifeTime ...

  4. Qt中利用QTime类来控制时间,这里简单介绍一下QTime的成员函数的用法:

    Qt中利用QTime类来控制时间,这里简单介绍一下QTime的成员函数的用法: ------------------------------------------------------------ ...

  5. 使用Oracle PROFILE控制会话空闲时间

    客户想实现对会话空闲时间的控制,下面是做的一个例子.Microsoft Windows [版本 6.1.7601] 版权所有 (c) 2009 Microsoft Corporation.保留所有权利 ...

  6. Progressive Web App是一个利用现代浏览器的能力来达到类似APP的用户体验的技术——不就是chrome OS吗?

    什么是Progressive Web App? Progressive Web App是一个利用现代浏览器的能力来达到类似APP的用户体验的技术,由Google实现,让浏览器打开的网址像APP一样运行 ...

  7. C# 获取操作系统空闲时间

    获取系统鼠标和键盘没有任何操作的空闲时间 public class CheckComputerFreeState { /// <summary> /// 创建结构体用于返回捕获时间 /// ...

  8. 查看MySQL 连接信息--连接空闲时间及正在执行的SQL

    MySQL 客户端与MySQL server建立连接后,就可以执行SQL语句了. 如何查看一个连接上是否正在执行SQL语句,或者连接是否处于空闲呢? 下面我们做下测试. 1.查看连接的空闲时间 首先看 ...

  9. oracle限制一个用户空闲时间

    alter system set resource_limit = true; create profile idletime limit idle_time 3; alter user outln ...

随机推荐

  1. native的详细用法

    目录 1.JNI:Java Native Interface 3.用C语言编写程序本地方法 一.编写带有 native 声明的方法的java类 二.使用 javac 命令编译所编写的java类,生成. ...

  2. angularjs和ajax的结合使用 (三)

    转眼九月份了,忙忙碌碌 发现今年还没开过张,写一篇吧. 15年在空闲时就倒腾过angularjs那玩意儿 ,觉得还是挺好的,李金龙那厚厚的一本书,只不过没有系统化应用.最主要的是原来有一个东西没有用到 ...

  3. 心得体会,搞清楚你为什么学习C++?

    小编作为一名初学者时,从来没问过自己学习C语言.C++等语言是为了什么? 一开始,接触到这个行业可以说是有种魔力引导我,感到了很大的兴趣,很有意思. 我试着读资料,报名学习,找资料,可算是功夫不负有心 ...

  4. mysql5.7.X版本only_full_group_by问题解决

    一.出错原因 最近因为开发数据库与部署数据库版本不同,带来了几个问题,其中only_full_group_by问题是之前没有遇到的. 具体报错如下 [Err] 1055 - Expression #1 ...

  5. #工具 Intellij IDEA中自定义的Maven Archetype管理

    背景,手贱在输入自定义的 archetype时后面多输入了一个空格 解决:自定义的Archetype 会保存在Windows下面的文件中 C:\Users\<user>\.IntelliJ ...

  6. Linux_常用命令简单介绍(netstat,awk,top,tail,head,less,more,cat,nl)

    1.netstat netstat -tnl | grep 443 (查看443端口是否被占用) root用户,用netstat -pnl | grep 443 (还可显示出占用本机443端口的进程P ...

  7. 用 PHP文件引入css样式

    html: <link rel="stylesheet" type="text/css" href="http://www.mysite.com ...

  8. Linux Rabbit的使用

    安装RabbitMQ 1.安装Erlang yum -y install epel-release yum -y update yum -y install erlang socat yum -y i ...

  9. 【原创】XAF CriteriaOperator 使用方式汇总

    1.CriteriaPropertyEditor [EditorAlias(EditorAliases.CriteriaPropertyEditor)] [CriteriaOptions(" ...

  10. LeetCode笔记:39. Combination Sum

    题目描述 给定一个无重复的正整数数组 candidates 和一个正整数 target, 求所有和为 target 的 candidates 中数的组合中.其中相同数的不同顺序组合算做同一种组合,ca ...