博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS魔法堂:初探传说中的setImmediate函数
阅读量:6793 次
发布时间:2019-06-26

本文共 2520 字,大约阅读时间需要 8 分钟。

一、前言                              

   由于JavaScript程序为单线程,因此在执行长时间的操作时(如循环和递归操作)到导致UI线程长期被阻塞,无法响应用户操作请求(如点击按钮等),让用户体验大打折扣。于是想到将一个长时间操作切片成N个小操作并异步执行,例如jsDeferred中的 Deferred.repeat函数 就提供这样的解决办法,其实质就是通过 setTimeout事件 或 script元素 的 onerror/onload事件 来异步调用这些小操作,从而尽早释放UI线程。

   从IE10开始引入了setImmediate接口来代替setTimeout来完成上述功能,下面将记录该接口的资讯,由于内容会涉及到event loop、调用栈等知识,而我对相关内容了解仍不全面,因此下面的内容若有纰漏请各位指正,谢谢!

 

二、同步和异步调用                        

  由于JavaScript是通过异步调用来尽早释放UI线程,因此我们先要了解同步和异步执行的具体含义:

  任务的执行实质上分为两步:①.执行,②.获取执行结果。

  同步执行:执行后等待直到获取执行结果;

  异步执行:执行后不等待,而是通过一系列手段(轮询、事件监听和event loop等)获取执行结果,而在执行后和获取结果前的那段时间可以介入其他任务操作。  

 

二、setTimeout(handler, 0)的问题                

  由于setTimeout存在时间精度,因此setTimeout(handler,0)中setTimeout事件插入事件队列的延时必定大于0ms,而handler的执行延时则更大了。具体为IE5~8和不插电源的IE9的时间精度为15.6ms,插电源的IE9和其他浏览器则为4ms。

  经微软和Chrome团队实验所得降低时间精度将会大大缩短笔记本的续航时间,也是就说更耗电,因此即使浏览器厂商有能力缩短时间精度,但基于多方面的考虑,依然保持上述的精度值。

    

三、setImmediate接口                     

  对于通过异步执行的手段对任务切片,由于UI线程得到释放从而提高用户体验,但相对于采用同步执行,整体的任务执行时间较被拉长,因此我们希望切片的小操作越快执行越好。而setImmediate接口则是为此而生的。

   setImmediate(handler) 并不像 setTimeout(handler, 0) 由event loop检测系统时间是否到点然后向事件队列插入一个事件,然后调用事件的回调方法handler。而是监控UI线程的调用栈,一旦调用栈为空则将handler压栈。

   理论上通过setImmediate执行异步调用的延时一定比通过setTimeout的短,但事实又是如何呢?

   我在IE11上操作测试,setTimout的延时为4ms左右,而setImmediate的延时为2ms左右。

   注意:

     1. 通过setImmediate的异步调用的延时不是0ms哦!

     2. 而且有时候setImmediate的延时比setTimeout的多1~2ms哦!

     3. 而且setImmediate和setTimeout的延时均比img元素onerror事件的延时长哦!

  推测:

     1. 对于setImmediate的延时有时比setTimeout的要长,由于setImmediate要先监控调用栈,若调用栈为空才压栈,那么在压栈之前event loop已经将setTimeout事件的回调函数压栈了。

     2. 对于两者均比img元素onerror事件的长,由于设置img.src后马上发起请求(不一定为网络IO)当加载失败时onerror事件则会比setTimeout事件先加入事件队列。

 

四、总结                            

  本文内容纰漏之处请各位指正,谢谢!

  尊重原创,转载请注明来自: ^_^肥仔John

 

五、参考                            

  http://developer.51cto.com/art/201109/292720.htm

  http://msdn.microsoft.com/library/ie/hh920766.aspx

  https://github.com/yuzujs/setimmediate

  http://www.nczonline.net/blog/2011/09/19/script-yielding-with-setimmediate/

如果您觉得本文的内容有趣就扫一下吧!捐赠互勉!

分类:
标签:
+加关注
3
1
上一篇:
下一篇:
posted @ 2014-12-09 13:54 阅读( 6454) 评论( 4)
  
2015-07-06 09:38
原来如此,谢博主解答
http://pic.cnblogs.com/face/505976/20140924144747.png
  
2016-04-06 10:51
博主,不太明白为什么img.onerror会快,onerror至少要发起请求才会触发啊。
  
[
楼主]
2016-04-06 14:57
LPegasus
采用data scheme uri发起的不是网络请求,推测是检测到data scheme uri不合法则马上出发error事件的缘故吧
http://pic.cnblogs.com/face/347002/20141205140116.png
  
3546514 2016/11/2 17:18:35
2016-11-02 17:18
都说了些什么鬼啊,我去
http://pic.cnblogs.com/face/677630/20160123165549.png
最新IT新闻:
·
·
·
·
·
»
最新知识库文章:
·
·
·
·
·
»

公告

作品:
本文转自 博客园博客,原文链接: ,如需转载请自行联系原作者
 
 
你可能感兴趣的文章
ffmpeg python库 - ffmpy
查看>>
LetsEncrypt SSL 证书签发(Nginx)
查看>>
JMX使用报java.lang.ClassNotFoundException: org.apache.naming.java.javaURLContextFactory
查看>>
linux下使用source /etc/profile保存配置后,新的环境变量只能在一个终端里面有效...
查看>>
表格查询
查看>>
DateTimePicker
查看>>
MySQL 查询优化器(二)
查看>>
Linux ssh工具之SSH Secure Shell Client
查看>>
双系统重装win7/Xp后如何恢复ubuntu引导
查看>>
ubuntu装锐捷认证 ruijieclient 需要配置ruijie.conf
查看>>
Android 手势滑动
查看>>
This function has none of DETERMINISTIC, NO SQL, o
查看>>
Mysql5.5编译安装
查看>>
centos7 crontab 计划任务
查看>>
进程的概念与管理
查看>>
调试家用路由器-前奏
查看>>
Mysql复制表结构,create table order like orderdetails;
查看>>
如何在JAVA 代码中调用PEGA Activity?
查看>>
expect
查看>>
数据库参数配置
查看>>