Javascript之旅——终点站:困惑的settimeout
有时候结局不是很美好,但起码这也算是一种结局,这个系列的最后一篇settimeout,这是一个让人困惑的函数,也是我一直在吐槽JS的
原因,我们看不到JS的源代码,setimeout同样也是,从始到终都是黑盒子的使用。
一:settimeout单线程的质疑?
所有的教科书都在说js是单线程模型,也说settimeout的执行函数会丢给js的内部执行队列,这其中还包括onlick事件以及一些xhr的回调函数。
乍一看貌似是这么一回事,既然要排队嘛,那肯定是FIFO的原则了,谁也无法保证准确的定时触发,就算精确的触发的,也不能保证在执行队列中
马上执行,因为要排队,如果我设定了5s触发,所以时间一定会在5s 以上,问题就出现在这里,这个5s触发的机制是什么样的???谁能告诉我
呢????既然js是单线程的,难道是js会不停的轮训“执行队列”吗?问执行函数5s时间到了吗?5s时间到了吗???我想JS肯定不会这么傻乎乎
做这么个“内旋”操作,因为如果我设定的触发时间是1年呢?难道还要内旋1年么???而且这种拉模式是相当耗费CPU时间的,那为了尽量节省
CPU的时间,是否会有其他线程来辅助setttimeout来做这个5s的机制呢?然后5s时间到了将setimeout中的执行函数推入js的内部执行队列呢?
到底合理的方式会是怎么样的?
二:在System.Threading.Timer中寻找灵感
因为setimeout的闭源,我看不到settimeout内部到底怎么做到5s触发的机制,非常遗憾,我也只能去找类似语言中的Timer机制,还好在C#
中也是有这样的一个定时器,看看能不能找到些灵感,然后我就大概看了下源码:
static void Main(string[] args)
{
System.Threading.Timer timer = new System.Threading.Timer(Run, "", , * * ); //30s Console.Read();
}

通过眼花缭乱的查找,终于明白,原来Timer仅仅是对一个Win32中CreateAppDomainTimer函数的封装,真是他们的坑货,先让你眼见为实。

其中的dueTime也就是我的Timer构造函数中的period参数,这里也就是30s,然后定时触发AppDomainTimerCallback函数,一段逻辑后再调用
Fire方法触发我们的CallCallback函数。



其实我们看到源码之后,发现Timer计时器其实是个假的,只是封装了Win32函数,并且也没有做到完完全全的30s,这是因为callback()是在调用
AppDomainTimerCallback函数之后触发的,这些逻辑也是需要耗费时间的,包括win32回调的误差,那现在有什么灵感呢?既然C#的多线程采用
工作线程去跑都有误差,那你单线程的settimeout又何德何能呢?那更不用谈用主线程去轮训settimeout这个很不现实的东西。
三:最后的一点猜测
通过对C#中的Timer原理的一些理解,我觉得settimeout应该是这样的,这其中的5s机制应该是丢给浏览器内核线程了,由浏览器内核线程去实
现这个5s的机制,如果5s时间到了,内核会将function函数塞给js的“内部执行队列”,由js主线程空闲的时候去得以执行。毕竟浏览器线程还是有很多
的,比如下面的IE9:

好了,不说了,说的再多也是猜测,结局并不完美,感谢大家对javascript系列的持续关注,也祝大家在新的一年工作顺利~~~
Javascript之旅——终点站:困惑的settimeout的更多相关文章
- JavaScript之旅(DOM)
JavaScript之旅(DOM) [TOC] 一.认识DOM 什么是 DOM? DOM 是 Document Object Model(文档对象模型)的缩写. DOM 是 W3C(万维网联盟)的标准 ...
- JavaScript之旅(三)
JavaScript之旅(三) 三.函数 在JavaScript中,定义函数的方式如下: function abs(x) { ... return ...; } 如果没有return,返回结果为und ...
- JavaScript之旅(二)
JavaScript之旅(二) 二.进阶知识 js的正则表达式 异常处理 调试 变量提升 表单验证 JSON javascript:void(0) JavaScript 代码规范 二.进阶知识 1. ...
- Javascript之旅(一)
Javascript之旅(一) 一.基础知识 基本语法 变量 数据类型 字符串 数组 对象 条件判断 循环 Map和Set iterable 为什么要学习JavaScript JavaScript 是 ...
- JavaScript DOM 编程艺术·setInterval与setTimeout的动画实现解析
先贴上moveElement()函数的大纲,为了方便观看,删了部分代码,完整版粘到文章后面. function moveElement(elementID,final_x,final_y,interv ...
- JavaScript之关闭轮询定时器(setTimeout/clearTimeout|setInterval/clearInterval)小结
已知: 1.1 开启Timeout程序: scope.setTimeout("functionName()" | functionHandle, timeValue) 返回值:ti ...
- JavaScript你所不知道的困惑(2)
困惑一: var obj1 = new Object(); var obj2 = obj1; obj1.name = "阳光小强"; alert(obj2.name); //输出结 ...
- JavaScript你所不知道的困惑(1)
困惑一: 先看一个样例: function test(){ message = "hi"; } test(); alert(message); 会输出字符串"hi&quo ...
- JavaScript定时调用函数(SetInterval与setTimeout)
setTimeout和setInterval的语法同样.它们都有两个參数.一个是将要运行的代码字符串.另一个是以毫秒为单位的时间间隔,当过了那个时间段之后就将运行那段代码. 只是这两个函数还是有差别的 ...
随机推荐
- WinForm小白的WPF初试一:从PropertyGrid控件,输出内容到Word(上)
学WinForm也就半年,然后转到WPF,还在熟悉中.最近拿到一个任务:从PropertyGrid控件,输出内容到Word.难点有: 一.PropertyGrid控件是WinForm控件,在WPF中并 ...
- Windows Server 2012 配置多用户远程桌面
前段时间因为需要多用户同时远程连接 windows server 2012,但找了半天也没找到远程桌面管理,最后从搜索中找到如下方法,经测试可行! 打开注册表,进入路径: [HKEY_LOCAL_MA ...
- spring笔记4 spring MVC的基础知识4
//todo 5,spring MVC的本地化解析,文件上传,静态资源处理,拦截器,异常处理等 spring MVC 默认使用AcceptHeaderLocalResolver,根据报文头的Accep ...
- hibnate 创建表的时候type=innodb报错
这个原因是在MYSQL5.5及以后版本中type=InnoDB 由ENGINE=InnoDB 代替. 解决办法,自己定义一个方言: package com.hotusm.dialect; /** * ...
- php高版本不再使用mysql_connect()来连接数据库
想用php生成一个mysql数据字典导出来,用到下面代码会 $mysql_conn = mysql_connect ( "$dbserver", "$dbusername ...
- mybatis 3的TypeHandler解析(null值的处理)
最近,在测试迁移公司的交易客户端连接到自主研发的中间件时,调用DAO层时,发现有些参数并没有传递,而在mapper里面是通过parameterMap传递的,因为有些参数为null,这就导致了参数传递到 ...
- flex的用途
一.可以利用flex来布局一个div在另一个div里面水平垂直居中 如:html代码: <div class="container"> <div class=&q ...
- 什么是闭包(closure),为什么要用它?
闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部. ...
- javascript --- 实时监听输入框值的变化
实时监听文本框值变化是非常常见的功能,通常最简单的办法就是用keyup,keydown来实现,但是这种方法有两个问题,一个是当直接复制粘贴的时候没法监听到事件,另外一个问题是在移动端,使用删除键删除输 ...
- SAP中发送邮件
WITH HEADER LINE, docdata LIKE sodocchgi1, objtxt WITH HEADER LINE, objpack WITH HEADER LINE, reclis ...