小编给大家分享一下JavaScript在nodejs环境下执行机制和事件循环的示例,希望大家阅读完这篇文章后大所收获、下面让我们一起去探讨吧!
1,说明
nodejs是单线程执行的,同时它又是基于事件驱动的非阻塞IO编程模型。这就使得我们不用等待异步操作结果返回,就可以继续往下执行代码。当异步事件触发之后,就会通知主线程,主线程执行相应事件的回调。
本篇文章讲解节点中JavaScript的代码的执行流程,下面是测试代码,如果你知道输出的结果,那么就不需要再看本篇文章,如果不知道输出结果,那么本片文章可帮助你了解:
console.log (1) setTimeout(函数(){ 新的承诺(函数(解决){ console.log (2) 解决() }) 不要犹豫(()=比;{console.log (3)}) }) setTimeout(函数(){ console.log (4) })
复杂的:
setTimeout(()=比;{ console.log (& # 39; 1 & # 39;) 新的承诺((解决)=比;{console.log (& # 39; 2 & # 39;);解决();}) 不要犹豫(()=比;{console.log (& # 39; 3 & # 39;)}) 新的承诺((解决)=比;{console.log (& # 39; 4 & # 39;);解决()}) 不要犹豫(()=比;{console.log (& # 39; 5 & # 39;)}) setTimeout(()=比;{ console.log (& # 39; 6 & # 39;) setTimeout(()=比;{ console.log (& # 39; 7 & # 39;) 新的承诺((解决)=比;{console.log (& # 39; 8 & # 39;);解决()}) 不要犹豫(()=比;{console.log (& # 39; 9 & # 39;)}) 新的承诺((解决)=比;{console.log (& # 39; 10 & # 39;);解决()}) 不要犹豫(()=比;{console.log (& # 39; 11 & # 39;)}) }) setTimeout(()=比;{console.log (& # 39; 12 & # 39;)}, 0) }) setTimeout(()=比;{console.log (& # 39; 13 & # 39;)}, 0) }) setTimeout(()=比;{console.log(& # 39; & # 39; 14日)},0) 新的承诺((解决)=比;{console.log (& # 39; 15 & # 39;);解决()}) 不要犹豫(()=比;{console.log (& # 39; 16 & # 39;)}) 新的承诺((解决)=比;{console.log (& # 39; 17 & # 39;);解决()}) 不要犹豫(()=比;{console.log (& # 39; 18 & # 39;)})
<强> 2。nodejs的启动过程强>
节点。js启动过程可以分为以下步骤:
- <李>调用platformInit方法,初始化nodejs的运行环境。李> <李>调用performance_node_start方法,对nodejs进行性能统计。李> <李> openssl设置的判断。李> <李>调用v8_platform。初始化、初始化libuv线程池。李> <李>调用V8::初始化、初始化V8环境。李> <李>创建一个nodejs运行实例。李> <李>启动上一步创建好的实例。李> <李>开始执行js文件,同步代码执行完毕后,进入事件循环。李> <李>在没有任何可监听的事件时,销毁nodejs实例,程序执行完毕。李>
<强> 3。nodejs的事件循环详解强>
nodejs将消息循环又细分为6个阶段(官方叫做阶段),每个阶段都会有一个类似于队列的结构,存储着该阶段需要处理的回调函数。
Nodejs为了防止某个阶段任务太多,导致后续的阶段发生饥饿的现象,所以消息循环的每一个迭代(迭代)中,每个阶段执行回调都有个最大数量。如果超过数量的话也会强行结束当前阶段而进入下一个阶段。这一条规则适用于消息循环中的每一个阶段。
3.1定时器阶段
这是消息循环的第一个阶段,用一个<代码> 代码>循环处理所有<代码> setTimeout 代码>和<代码> setInterval> 代码的回调。
这些回调被保存在一个最小堆(最小堆)中。这样引擎只需要每次判断头元素,如果符合条件就拿出来执行,直到遇到一个不符合条件或者队列空了,才结束计时器的阶段。
计时器阶段中判断某个回调是否符合条件的方法也很简单。消息循环每次进入计时器的时候都会保存一下当时的系统时间,然后只要看上述最小堆中的回调函数设置的启动时间是否超过进入计时器时保存的时间,如果超过就拿出来执行。
3.2等待I/O调阶段
执行除了<代码>关闭回调代码>,<代码> setTimeout() 代码>,<代码> setInterval() 代码>,<代码> setImmediate() 代码>回调之外几乎所有回调,比如说<代码> TCP连接发生错误代码>,<代码> fs。读代码>,<代码>插座> 代码等IO操作的回调函数,同时也包括各种错误的回调。
3.3闲置,准备阶段
系统内部的一些调用。
3.4调查阶段,重要阶段
这是整个消息循环中最重要的一个阶段,作用是等待异步请求和数据,因为它支撑了整个消息循环机制。