CyanSalt / notebook

3 stars 0 forks source link

浏览器异步任务函数对比 #1

Open CyanSalt opened 6 years ago

CyanSalt commented 6 years ago

path: async-fns


注:此处仅对比独立线程的异步函数,使用 postMessage 等多线程方式暂不考虑。另外 Promise 使用的是 micro task,并没有离开当前消息循环,这里也暂不考虑。

截至目前(2018.7.6)有四个函数可以用于异步任务调用:

TL;DR

setTimeoutsetInterval 适合后台运行一些队列任务,但纯计算任务应该使用 Web Worker;requestAnimationFrame 适合处理实时的 UI 任务,requestIdleCallback 适合处理耗时的更新 UI 操作。

setTimeoutsetInterval

setTimeoutsetInterval 在目前浏览器的实现上应该是类似的,添加一个延迟指定时间的定时器任务,区别是 setInterval 定时器将循环执行,而 setTimeout 仅执行一次。

setTimeoutsetInterval 的第一个参数可以是字符串或函数,如果是字符串则会隐式调用内部解释器,类似 evalnew Function。第三个及后面的参数如果指定,则会被传入回调函数中(IE9以下不支持,但可以 Pollyfill)

第二个参数用来指定延迟的毫秒数,如果不声明默认为 DOM_MIN_TIMEOUT_VALUE,如果比这个值小也会被强行置为这个值。在最新版本的主流浏览器中这个值大概是 4ms。

在 Chrome 中(其他浏览器暂未测试),当标签页不在前台运行时,这个最小值会变成 1000ms。猜测当页面处在隐藏的 iframe 中也会有类似的行为,暂未确定。

在 Firefox 中,如果脚本被识别为某些页面统计脚本,例如 GA,则这个最小值会变成 10000ms。

据某些 Web 文章记载,过去的浏览器曾有以下行为:

requestAnimationFrame

requestAnimationFrame 的行为类似于 setTimeout 仅使用第一个参数的情况,且只能传递函数作为参数。回调函数可以接收一个值等于 performance.now() 的参数。

requestAnimationFrame 通常来说使用的是 Web 标准帧率(延迟 1/60s 执行)

requestAnimationFrame 在非前台的标签页或隐藏的 iframe 中会停止运行

requestIdleCallback

requestIdleCallback 的参数与 requestAnimationFrame 完全一致,但它可以指定第二个参数。requestIdleCallback 在下一帧到来时如果浏览器不处于空闲状态,则会继续延迟一帧执行,直到浏览器进入空闲,或者第二个参数的 timeout 属性这么多毫秒过去。