页面流畅与 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. 爬虫之图片懒加载技术及js加密

    图片懒加载 图片懒加载概念: 图片懒加载是一种网页优化技术.图片作为一种网络资源,在被请求时也与普通静态资源一样,将占用网络资源,而一次性将整个页面的所有图片加载完,将大大增加页面的首屏加载时间.为了 ...

  2. 我的第一个chrome浏览器扩展 5分钟学习搞定

    注意: 文件名必须是 manifest, ,注意扩展名是json, 新建一个文件夹,然后创建一个文本文件,作为这个扩展程序的配置文件,所以文件名是manifest.json, 感谢https://ww ...

  3. matplotlia应用

    一.简单使用 使用函数 plt.polt(x,y,label,color,width) 根据x,y 数组 绘制直,曲线 import numpy as np #引用numpy库,从新命名它为np(以后 ...

  4. Oracle导入大数据量(百万以上)dmp文件,报错ora-12592 :包错误

    进行自动化测试过程中,发现需要重新搭建一套自动化测试库,然后利用pl/sql对数据库导出: 进行导入后发现报错ora-12592 :包错误 原因分析,数据量过大,传输超时,需要在Oracle服务端以及 ...

  5. OneNote中添加代码问题

    OneNote是我最常用的笔记本,然而粘贴代码很麻烦,之前只能屏幕截图如Snipaste自带截图什么的,后来才知道win10自带有win+shift+s自动剪切到草图板上的功能, 然而还是很麻烦. 在 ...

  6. hive动态分区和混合分区

    各位看官,今天我们来讨论下再Hive中的动态分区和混合分区方面的一些知识点以及相关的一些问题. 前面我们已经讲过管理表和外部表的一般分区的一些知识点,对于需要对表创建很多的分区,那么用户就需要些很多的 ...

  7. phantomjs api文档

    phantomjs实现了一个无界面的webkit浏览器.虽然没有界面,但dom渲染.js运行.网络访问.canvas/svg绘制等功能都很完备,在页面抓取.页面输出.自动化测试等方面有广泛的应用. 详 ...

  8. 小程序重新封装打印函数console.log

    习惯性使用console.log打印获取到的数据,信息等,然后上星期大佬看见了说怎么那么多打印信息出来,线上那个也是吗?问我能不能线上的就不打印出来? 我就说那就封装一个打印函数呗. 重写一个没问题, ...

  9. The SQL Server instance returned an invalid or unsupported protocol version during login negotiatio

    在使用.net core 连接sqlserver的时候遇到了这个问题 从字面意思理解大致是个什么版本不支持, 谷歌一下吧,ok,看到这个2000我就知道什么问题了 我的数据库还是2000的,总算把20 ...

  10. python elasticsearch 批量写入数据

    from elasticsearch import Elasticsearch from elasticsearch import helpers import pymysql import time ...