美文网首页
RequestAnimationFrame & RequestI

RequestAnimationFrame & RequestI

作者: 隐号骑士 | 来源:发表于2020-02-07 13:08 被阅读0次

对于高频连续执行任务(如动画等),怎么处理呢?

setInterval

        console.log('begin', Date.parse(new Date()))
        function step() {
            console.log('setInterval', Date.parse(new Date()))
            start++;
            element.style.left = (parseInt(element.style.left.slice(0, -2)) + 1) + 'px';
            if (start > 200) {
                clearInterval(timer)
            }
        }

        let timer = setInterval(step, 10)

假如同时插入了其它任务:

        console.log('begin', Date.parse(new Date()))
        setTimeout(() => console.log('setTimeout1', Date.parse(new Date())), 1000)
        for (let i = 0; i < 100000; i++) {
            setTimeout(() => console.log('setTimeout', Date.parse(new Date())), 1)
        }

会发现定时器是不准确的:


image.png

requestIdleCallback

React Fiber中的任务调度与此API息息相关

它调用函数时会给函数传两个参数:

  • timeRemaining(): 当前帧还剩下多少时间
  • didTimeout: 是否超时

它的作用是是在浏览器一帧的剩余空闲时间内执行任务,
即,在一帧结束前且没有别的高优先级任务的情况下,再执行该任务,
也就是说,requestIdleCallback的优先级低.

页面是一帧一帧绘制出来的,当每秒绘制的帧数(FPS)达到 60 时,页面是流畅的,小于这个值时,用户会感觉到卡顿。
1s 60帧,所以每一帧分到的时间是 1000/60 ≈ 16 ms。

示例:

        function step(timestamp) {
            start++;
            element.style.left = (parseInt(element.style.left.slice(0, -2)) + 1) + 'px';
            if (start < 200) {
                console.log('requestIdleCallback', Date.parse(new Date()))
                window.requestIdleCallback(step)
            }
        }

        step()

        console.log('begin', Date.parse(new Date()))
        for (let i = 0; i < 100000; i++) {
            setTimeout(() => console.log('setTimeout', Date.parse(new Date())), 1)
        }

结果


image2.png

所有的requestIdleCallback都在主线程任务完成之后进行。

requestAnimationFrame

它的定义就是在浏览器下次绘制之前将会执行这个方法的回调。
即,每次绘制前都会优先执行requestAnimationFrame的任务
也就是说requestAnimationFrame的优先级高

它调用时给函数传一个参数:

  • 一个 long 整数,请求 ID ,是回调列表中唯一的标识。是个非零值,没别的意义。

示例:

        function step() {
            start++;
            element.style.left = (parseInt(element.style.left.slice(0, -2)) + 1) + 'px';
            if (start < 200) {
                console.log('requestAnimationFrame', Date.parse(new Date()))
                window.requestAnimationFrame(step);
            }
        }

        window.requestAnimationFrame(step);

        console.log('begin', Date.parse(new Date()))

        for (let i = 0; i < 100000; i++) {
            setTimeout(() => console.log('setTimeout', Date.parse(new Date())), 1)
        }

执行的结果:

image3.png

相关文章

网友评论

      本文标题:RequestAnimationFrame & RequestI

      本文链接:https://www.haomeiwen.com/subject/wlcmxhtx.html