一、信号事件的回调
非常类似qt开发中signgl/slot机制,很好理解。函数的对象(包括使用通用的EventEmitter的对象或者自定义函数的对象)可以发射signal,然后对应的注册函数就回响应执行。
1.使用EventEmmiter发射信号
//a.直接用emitter发射
var emitter=
new
events.EventEmitter();
emitter.on(
"signal"
, function(num){
console.log(
"slot函数响应,获取参数:"
+num);
});
//b.发出signal
console.log(
"before"
);
emitter.emit(
"signal"
,
12345
);
console.log(
"after"
);
//output:
//before
//slot函数响应,获取参数:12345
//after
|
使用自定义函数的对象发射信号只需要把a部分改成下面样子:
//a.使用自己定义的函数对象
function myfunc(){
events.EventEmitter.call(
this
);
}
util.inherits(myfunc,events.EventEmitter);
var myF =
new
myfunc();
myF.on(
"signal"
, func);
|
2. 本身是同步的
值得注意的是,通过输出可以发现,响应函数是同步,而之所以信号响应的回调函数能够达到异步工作的效果,是因为发出信号的工作线程本身是异步的。
二、其他回调形式
nodeJs主线程是基于事件驱动的单线程程序,事件轮询时核心。
实际上,nodeJs是通过异步api与回调函数的配合完成的单线程编程,多线程的部分(基于x-nix系统底层libuv异步库)体现在异步的api上因此对编程是透明的,从而简化了开发。
下面是几种除了事件外的,常见的回调方式:
f = function(b) {
//递归打印
console.log(b);
if
(b==
5
){
return
;
}
return
process.nextTick(function() {
return
f(b +
1
);
});
};
setTimeout(function () {
console.log(
'--------------setTimeout------------'
);
},
0
);
setImmediate(function () {
console.log(
'--------------setImmediate------------'
);
});
f(
1
);
//output:
//1
//2
//3
//4
//5
//--------------setTimeout-----------
//--------------setImmediate---------
|
根据输出可以猜到:
1.process.nextTick(func)
永远在工作栈本轮执行完毕后执行;
2. setTimeout(func,0)
在下轮事件队列的前面
3. setImmediate(func)
在下轮事件队列的最最后面
4.异步的信号事件
没做试验,不出意外在setTimeout与setImmediate之间响应
三、主线程的事件轮询
没找到好图。差不多意思下把。
我理解的主线程事件驱动:
1.一共由两个东西,工作栈区与事件任务队列。前者并非真的栈,而是串行的一系列待执行代码,而后者是真正的分层次的FIFO的队列数据结构。
2.每轮的工作栈区叫做一个tick。每次将本轮tick执行完毕,再将事件任务队列中的所有任务搬到工作栈区,开始下轮tick。
3.期间遇到的timer,callback,poll,immediate等事件按照如下图层次串成事件任务队列(顺序上先分层次,然后按触发时间先后入队)。
4.异步的事件由异步api自己调底层系统库解决,开发者只需充分考虑事件处理。
ref:
[1] Understanding the Node.js Event Loop Trevor Norris by Trevor Norris:https://nodesource.com/blog/understanding-the-nodejs-event-loop
[2] nodeJs docs: https://nodejs.org/docs/latest/api/events.html