setTimeout(fn, 15)这样的东西到底有没有意义?

Review


    setTimeout/setInterval是JavaScript中很常见的两个超时函数,常用来制作动画或者异步操作( setTimeout(fn, 0) )。

    setTimeout(fn, delay) 中的第二个参数是 delay 是一个以毫秒为单位的整数,表示经过 delay 时间后开始调用fn。但是由于JavaScript是单线程的,setTimeout这类通过web API的调用会被维护在一个队列中,所以fn真正调用的时间是 >= delay

正题


    在今年秋招面试的时候被问到了关于setTimeout的限制的问题,一下子就懵掉了。超时调用和异步的问题都知道,但是从来没想过setTimeout会有什么限制。后来面试快结束的时候和面试官(Givon)聊了一下他说 当delay<16的时候delay是没有意义的

    然后撸主真的是涨姿势了,从来没听说过这个问题,但是 16 这个数字让我有点纠结。

    百度查了很多资料都没有这方面的内容,后来想起张鑫旭的一篇关于requestAnimationFrames 博客,里面有讨论过关于浏览器帧频的问题。感觉Givon说的应该就是这个问题。

    里面有提到由于很大一部分浏览器刷新频率都是16ms,所以使用超时函数制作动画的时候如果设置的时间没有卡紧帧频的话有可能会出现掉帧的情况。因此才会出现了 requestAnimationFrame 这个替代方案。

    后来在知乎上看过类似的讨论,撇开动画不说 delay的极限值取决于处理器的性能 。感觉这个结论更接近正确的答案。

写了一个小demo测试一下:

    var handler,
        prev = Date.now(),
        count = 0,
        current;
    handler = setInterval(function() {
        current = Date.now();
        console.log(current - prev);
        prev = current;
        count++;

        if(count >= 100)
            clearInterval(handler);
    }, 1);

结果(还没弄好图床,就不贴图了):

62
4
2
2
4
7
5
6
5
...

除了第一个62s外,超时还算是平均,基本维持在5s左右。

    在写demo代码的时候想到 console.log 这种IO操作会不会大幅度拖慢执行速度造成结果不准确,然后先采用了数组缓存结果再统一输出:

    var arr = [],
        handler,
        prev = Date.now();
    handler = setInterval(function() {
        var current = Date.now();
        arr.push(current - prev);
        prev = current;

        if(arr.length >= 100)
            clearInterval(handler);
    }, 1);
    console.dir(arr);

后来发现两者的速度基本没差多少,然后我内心就一片卧槽了。console.log的效率那么高直逼内存了?谷歌大法好?

后来想了一下还有另外一个可能,后来百度了一下,证实了这个猜想: console.log其实是一个异步操作 = =。。。所以平时输出的时候结果有可能不对。用了这玩意那么多年,现在才知道真是孤陋寡闻了。

Summary


setTimeout(fn, 15)这样的函数在在制作动画的时候一般是没有意义的,为了避开掉帧的风险享受丝般顺滑的动画效果可以使用requestAniamtionFrame来替代(旧浏览器可能存在一定兼容问题)。但是撇开动画(除了动画我还真想不出还有什么需要这么高频超时运作的场景),delay<15还是能跑的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值