• home > webfront > ECMAS > javascript >

    requestIdleCallback对比setTimeout/setImmediate/requestAnimationFrame

    Author:zhoulujun Date:

    setTimeout、setInterval、setImmediate、requestAnimationFrame、requestIdleCallback,都是异步回调,有何异同?requestIdleCallback可以做什么,不推荐做什么?

    setTimeout、setInterval、setImmediate

    setTimeout、setInterval不用多讲,setImmediate至今chrome不支持。

    在《弄懂javascript的执行机制:事件轮询|微任务和宏任务

    而setTimeout、setInterval、setImmediate的回调函数,追加在次轮循环

    所以,需要注意的是

    setTimeout()只是将事件插入了"任务队列",必须等到当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数。要是当前代码耗时很长,有可能要等很久,所以并没有办法保证,回调函数一定会在setTimeout()指定的时间执行

    setInterval(fn,ms)不是每过ms秒会执行一次fn,而是每过ms秒,会有fn进入Event Queue。一旦setInterval的回调函数fn执行时间超过了延迟时间ms,那么就完全看不出来有时间间隔了。这句话请读者仔细品味

    setImmediate相对于setTimeout,,没有最少4毫秒的间隔。

    一般容易忽略的是,setTimeout、setInterval、setImmediate,都可以传参数。setTimeout、setInterval,前面两项为callback,delayTime,后面追加参数为 回调函数的参数

    setTimeout(function() {
        console.log(arguments); // Arguments(3) ["a", "b", "c", callee: ƒ, Symbol(Symbol.iterator): ƒ]
    }, 0, 'a', 'b', 'c');

    其他处理方式:1. let。2. IIEF。

    requestAnimationFrame

    requestAnimationFrame和setTimeout有点相似,不同之处在于,setTimeout是在等待指定毫秒数之后被调用,而requestAnimationFrame则是在每次屏幕被刷新时被调用

    requestIdleCallback

    requestIdleCallback将在浏览器的空闲时段内调用的函数排队。和timeout一样,函数一般会按先进先调用的顺序执行,然而,如果回调函数指定了执行超时时间timeout,则有可能为了在超时前执行函数而打乱执行顺序。

    var handle = window.requestIdleCallback(callback,{timeout})
    window.cancelIdleCallback(handle);

    因为JavaScript的单线程特性,为了提升性能,我们有时候会想把一些不是特别重要的或者一些非常耗时的操作放在在浏览器空闲的时候去执行,那怎么判断当前浏览器是否空闲呢,requestIdleCallback提供了这样的一个功能

    requestAnimationFrame会在每次屏幕刷新的时候被调用,而requestIdleCallback则会在每次屏幕刷新时,判断当前帧是否还有多余的时间,如果有,则会调用requestAnimationFrame的回调函数。

    requestIdleCallback里面可以执行DOM修改操作吗?

    requestIdleCallback回调的执行说明前面的工作(包括样式变更以及布局计算)都已完成。如果我们在callback里面做DOM修改的话,之前所做的布局计算都会失效,而且如果下一帧里有获取布局(如getBoundingClientRect、clientWidth)等操作的话,浏览器就不得不执行强制重排工作,这会极大的影响性能,另外由于修改dom操作的时间是不可预测的,因此很容易超出当前帧空闲时间的阈值,故而不推荐这么做。

    推荐的做法是在requestAnimationFrame里面做dom的修改,可以在requestIdleCallback里面构建Document Fragment,然后在下一帧的requestAnimationFrame里面应用Fragment

    除了不推荐DOM修改操作外,Promise的resolve(reject)操作也不建议放在里面,因为Promise的回调会在idle的回调执行完成后立刻执行,会拉长当前帧的耗时,所以不推荐。

    推荐放在requestIdleCallback里面的应该是小块的(microTask)并且可预测时间的任务。




    参考内容:

    js中setTimeout,requestAnimationFrame,requestIdleCallback的区别和应用 https://blog.csdn.net/handsomexiaominge/article/details/89057456

    setTimeout第三个参数 https://www.zhuyuntao.cn/setTimeout第三个参数

    https://developer.mozilla.org/zh-CN/docs/Web/API/Window/setTimeout

    https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback

    你应该知道的requestIdleCallback https://segmentfault.com/a/1190000014457824



    转载本站文章《requestIdleCallback对比setTimeout/setImmediate/requestAnimationFrame》,
    请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/js/2019_1220_8488.html