小痴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里,及其重要的指示板块,我也学得不好,只能说先把明白了的部分说出来,再接下来的学习生活中,慢慢补齐。