TAT.Cson 更快的异步执行
In Web开发 on 2014年03月03日 by view: 40,533
20

如果要异步执行一个函数,我们最先想到的方法肯定会是setTimeout
例如:setTimeout(function( /* 1s后做点什么 */){},1000}

那如果说要最快速地异步执行一个函数呢?
是否会是:

可惜的是,浏览器为了避免setTimeout嵌套可能出现卡死ui线程的情况,为setTimeout设置了最小的执行时间间隔,不同浏览器的最小执行时间间隔都不一样。chrome下测试 setTimeout 0 的实际执行时间间隔大概在12ms左右。

那么如果想最快地异步执行一个函数,有没有什么可以提速的方法呢?

先来看看浏览器端,有哪些常用的异步执行方法

setImmediate:该方法去实现比setTimeout 0 更快的异步执行,执行时间更接近0ms,但是只有IE/node支持。

requestAnimationFrame:做动画循环的时候经常会用到这个方法,该方法只会在浏览器刷新ui的时候执行,刷新ui的频率最大一般为60fps,所以requestAnimationFrame一般情况下比setTimeout 0 更慢一些。

除了使用异步函数外,还有一些方法可以实现异步调用

利用onmessage:
和iframe通信时常常会使用到onmessage方法,但是如果同一个window postMessage给自身,会怎样呢?其实也相当于异步执行了一个function
例如:


另外,还可以利用script标签,实现函数异步执行,例如:



把script添加到文档也会执行onreadystatechange 但是该方法只能在IE下浏览器里使用。

那么 这几种方法,谁最快?

测试了一下,

chrome下:

setImmediate:不可用。
setTimeout 0:12ms
onmessage:6ms
onreadystatechange:不支持

chrome下,onmessage比setTimeout 0 更快。

firefox下:

setImmediate:不可用。
setTimeout 0:7ms
onmessage:7ms
onreadystatechange:不支持

firefox下,onmessage和setTimeout 0 速度相当。

IE9:

setImmediate:不可用。
setTimeout 0:11ms
onmessage:7ms 10ms
onreadystatechange:2ms

IE9下,onreadystatechange的时间比另外两者要快得多。

总体情况下,setImmediate < readystatechange < onmessage < setTimeout 0 < requestAnimationFrame
因此我们可以简单封装一个快速执行异步function的方法:

原创文章转载请注明:

转载自AlloyTeam:http://www.alloyteam.com/2014/03/faster-asynchronous-execution/

  1. rambo 2017 年 7 月 6 日

    https://github.com/shahyar/setZeroTimeout-js/blob/master/setZeroTimeout.js 跟您第二个想法一样

  2. tormahiri 2014 年 11 月 15 日

    不错误的文章

  3. Kpaxqin 2014 年 9 月 16 日

    关于时钟还有个问题
    在chrome下(其它浏览器还没测)
    var i = 0;
    setInterval(function(){
    if (i == 10){ //每1秒输出一次当前
    console.log(new Date());
    i = 0;
    }else{
    i++;
    }
    }, 100)
    切换其它标签页浏览一会儿,再切回,如下最后一条console打印,足足间隔了有接近10秒
    似乎【在浏览其它标签页时,setInterval被阻塞了】
    Tue Sep 16 2014 11:35:32 GMT+0800 (中国标准时间) test.html:16
    Tue Sep 16 2014 11:35:33 GMT+0800 (中国标准时间) test.html:16
    Tue Sep 16 2014 11:35:35 GMT+0800 (中国标准时间) test.html:16
    Tue Sep 16 2014 11:35:44 GMT+0800 (中国标准时间)

    但是
    setInterval(function(){
    console.log(new Date());
    }, 1000)
    则不会有类似的问题

  4. style 2014 年 7 月 17 日

    5555555

  5. style 2014 年 7 月 17 日

    tttttt

  6. style 2014 年 7 月 17 日

    tttttttttttttt

  7. fredshare 2014 年 6 月 25 日

    都是毫秒级别的,何必如此计较

  8. gdut-zdc 2014 年 3 月 24 日

    博主,ui线程卡死指的是两个任务同时进入到ui线程内,导致ui线程卡死吗?求指教啊,这里困扰了我好几天了,找了好些资料,陷入思维沼泽了。求搭救啊。能否回复一下呀..

  9. gdut-zdc 2014 年 3 月 24 日

    你好,你说的“浏览器为了避免setTimeout嵌套可能出现卡死ui线程的情况,为setTimeout设置了最小的执行时间间隔”这句话是怎么理解的?可否指教一下。

    • TAT.dmyang

      TAT.dmyang 2014 年 4 月 6 日

      setTimeout的延迟时间最短是16ms,小于10ms会自动设置成16ms

  10. gdut-zdc 2014 年 3 月 22 日

    用settimeout这种方法来模拟异步执行javascript并不是真正的异步执行。目前javascript并不支持多线程。

  11. Kevin 2014 年 3 月 22 日

    执行时间间隔用什么工具测试出来的

    • Sigma 2015 年 5 月 26 日

      console.time(‘Hello’);
      setTimeout(function(){
      console.timeEnd(‘Hello’);
      }, 0);

      Hello: 1.098ms

  12. javascript、jQuery学习系列文章 - ^styleYan 2014 年 3 月 13 日

    […] javascript更快的异步执行 […]

  13. TAT.Johnny

    TAT.Johnny 2014 年 3 月 8 日

    看过一篇浏览器时钟精度的文章, 可以参考一下
    http://www.ituring.com.cn/article/1828?q=settimeout

  14. kazaff 2014 年 3 月 4 日

    看了第一行就发现错了:

    例如:setTimeout(function( /* 1s后做点什么 */){},1000}

    • MiCoo 2014 年 3 月 5 日

      瑕不掩瑜啦

    • krew 2014 年 3 月 17 日

      哈哈,放错地了。。

    • Jack Works 2014 年 6 月 15 日

      其实这样放也是可以执行的啊 = =

      • Sigma 2015 年 5 月 26 日

        注释没问题,但括号没闭合。

发表评论