在Node.js的定时器的实现
最后一篇文章提到,在节点中,计时器不是由一个新的开放
线程实现的,而是直接在事件循环中完成的。下面是几个Javascript定时器和与节点相关的源代码实例,分析如何在节点中实现定时器
功能。
Javascript中定时器
函数的特性
无论节点或
浏览器,有两setTimeout和setInterval定时器功能,其
工作特点是基本相同的。因此,以Node为例进行分析。
我们知道在Javascript定时器定时中断不同,在
计算机的底层。当中断到来时,当前
执行的代码将中断执行定时中断
处理,而Javascript定时器超时,如果当前线程的执行不执行代码,执行相应的回调函数;如果在执行当前代码,Javascript引擎不会中断当前的代码执行的回调,不会打开新线程执行一个回调,但执行代码来处理。
console.time(A)
setTimeout(){()函数(
Console.timeEnd(A);
},100);
var I=0;
为了(;;我< 100000;我+ +){ }
通过执行上面的代码,你可以看到最终的输出时间是100ms左右,但几秒钟。这表明在循环完成后,定时回调函数实际上并没有被执行,但推迟到循环结束。事实上,在Javascript代码的执行,所有的事件无法处理,和新的事件必须在当前代码是完整的处理。这就是为什么浏览器失去响应,在浏览器中
运行的Javascript代码时费时。为了应对这种
情况,我们可以采取收益的过程技能,将代码分成小(块),每处理一个在短时间内实现协议处理setTimeout块后,在这段自由提姆e,可以在事件队列中处理浏览器节点。
补充资料
高级
程序和第三版高级技术的高级程序设计和第二十二章更
详细地讨论了高级定时器和输出过程。
节点中定时器的实现
通过libuv的uv_loop_t
类型初始化
博客中提到的节点称libuv的uv_run函数开始default_loop_ptr安排事件,并default_loop_ptr指向一uv_loop_t型变default_loop_struct。当节点
启动时,它调用uv_loop_init(default_loop_struct)来初始化它,和uv_loop_init选择功能如下:
国际uv_loop_init(uv_loop_t *环){
…
循环>时间= 0;
uv_update_time(环);
…
}
你可以看到,循环时间字段指定第一至0,然后uv_update_time函数被调用时,它将最新的计数时间loop.time。
初始化后,default_loop_struct.time的初始值。与时间相关的
操作将与此值进行比较,以确定是否调用相应的回调函数。
libuv的事件调度
核心 如前所述,该uv_run功能的libuv图书馆的核心部分实现事件循环,和下面的流程图:
下面是与上面计时器相关的逻辑的简要说明。
更新当前循环的时间字段,该字段标记当前循环的概念;
检查循环是否活着,也就是检查是否有一个
任务(处理程序/请求)在循环中进行处理,如果没有,则不需要循环。
检查已
注册的计时器。如果计时器中的指定时间落在当前时间的后面,则表示计时器已经到达,因此执行相应的回调函数。
一旦执行I/O轮询,即阻塞线程并
等待I/O事件发生。如果在下一个计时器过期时没有I/O完成,则停止等待并执行下一个计时器的回调。
如果存在I/O事件,则执行相应的回调。因为在执行回调时间中可能有另一个计时器过期,请再次检查计时器并在这里执行回调。
(事实上(4))它更复杂,不只是一步,但描述只是为了避免其他细节,而是专注于计时器的实现。)
节点总是叫uv_run until循环不再活着。
在节点timer_wrap和定时器
在节点上,有一个timerwrap类注册为在节点timer_wrap模块。
node_module_context_aware_builtin(timer_wrap,结::::timerwrap初始化)
的timerwrap类基本上是uv_timer_t直接封装,并node_module_context_aware_builtin是节点使用登记的内置模块的宏观。
在这一步之后,Javascript可以得到该模块操作。src / / timers.js lib
文件是通过Javascript的形式封装的,和timer_wrap功能,如exports.settimeout,exports.setinterval和exports.setimmediate出口。
节点启动和全局初始化
最后提到,当节点启动时,它将加载执行环境LoadEnvironment(env)。在这个函数中很重要的一步是加载SRC / Node.js和执行。SRC / Node.js将加载指定模块和初始化全局和过程。当然,setTimeout和其他的功能将由SRC / js绑定到全局对象。
以上是本文的全部内容,希望大家能喜欢。