vlambda博客
学习文章列表

小痴Nodejs升级路---事件循环eventloop

事件循环必然是与node.js非阻塞IO有关,当你学习python的时候,肯定不会接触到什么时间循环,当然你不一定,我是直接没有接触过。所以这也是异步编程里的知识块。

来看一看书本上的解释,到底什么是事件循环。

事件循环:Node自身的执行模型,正是它使得回调函数十分普遍。在进程启动时,Node便会创建一个类似于While(ttrue)的循环,每执行一次循环体的过程我们称为Trick。每个Trick的过程就是查看是否有事件待处理,如果有,就取出事件及其相关的回调函数。如果存在关联的回调函数,就执行它们。然后进入一个循环,如果不再有事件处理,就退出进程。流程图如下:


Trick流程图


这就是官方解释,看完了不懂?不懂就对了,我抄完了还是不懂呢。所以有了流程图,有了流程图大概就知道了,还是不懂?也不怕。我们待会来点代码帮助理解。

先来分解一下,书上说,类似于while(True)。那我们用代码来实现一下while(True),当然不能直接使用while(trhe)。人家只是像,又不是。

const eventloop = { loop(){ //先写循环方法 setTimeout(this.loop.bind(this), 50); //执行下一次循环 }}


好了,这就完成了一个类似while(true)。然后我们再在中间添加事件检测,就完成了eventloop了。那事件肯定有先后到来嘛,总不能老是让别人插队,所以可以肯定的是在eventloop中有个队列,有了队列,我们只用一直检测队列的长度,如果队列长度不等于零,那么就弹出队列里的事件。然后代码如下:

const eventloop = { queue: [], //队列 loop(){ while (this.queue.length){ //一直检测队列的长度 var callback = this.queue.unshift(); //弹出队列里的事件            callback(); //调用 } //先写循环方法 setTimeout(this.loop.bind(this), 50); //执行下一次循环 }}


有了检测事件的方法,当然我得往队列里添加事件,不然怎么循环执行呢?代码如下:

const eventloop = { queue: [], loop(){ while (this.queue.length){ var callback = this.queue.shift(); callback(); } //先写循环方法 setTimeout(this.loop.bind(this), 50); //执行下一次循环    },     add(callback){ //往队列里添加事件 this.queue.push(callback); }}


书上说,进程启动的时候,就会自动创建这个eventloop,我们这个是山寨的简易版本,那怎么运行呢?请看下面大块代码:

const eventloop = { queue: [], loop(){ while (this.queue.length){ var callback = this.queue.shift(); callback(); } //先写循环方法 setTimeout(this.loop.bind(this), 50); //执行下一次循环 },  add(callback){ //往队列里添加事件 this.queue.push(callback); }}
eventloop.loop();
setTimeout(() => { eventloop.add(()=>{ console.log('first callback'); })}, 500);
setTimeout(function(){ eventloop.add(function(){ console.log('second callback'); })}, 800);


终端运行之后,就会打印出了first callback,然后再打印second callback

既然是山寨简易的,当然和实际版本是有很大区别的。真要是那么简单,Node.js也不会那么火爆了。实际中肯定不会是50ms那么久才再次执行loop。事件也不会只有一个回调函数。比如在eventloop里面可能还有定时操作队列,文件操作队列,然后定时执行事件等等。


Node.js调用栈的底部就是eventloop里面触发的事件,可以理解为上面代码中的callback。所以上一节的callback是调用栈的底部,所以用try。。catch就抓不住错误。


其实eventloop,看着简单,是Node.js里,及其重要的指示板块,我也学得不好,只能说先把明白了的部分说出来,再接下来的学习生活中,慢慢补齐。