在web前端的编程中,事件的应用十分广泛,DOM上的各种事件,比如onclick 、onfocus等等。
在ajax大规模应用之后,异步请求更是得到广泛的认同,而ajax亦是基于事件机制的。
Node.js的事件机制是基于V8引擎实现的事件驱动I/O,充分呢利用了异步I/O解决了单线程编程模型的性能瓶颈。
事件机制的实现
Node.js内置了events模块,Events模块(events.EventEmitter)是一个简单的事件监听器模式的实现。具有addListener/on,once,removeListener,removeAllListeners,emit等基本的事件监听模式的方法实现。
第一个events示例,events-1.js:
var events = require('events');
//开一家餐馆
var restaurant = new events.EventEmitter();
/*
EventEmitter.emit(event, [arg1], [arg2], [...]) 触发指定事件
参数1:event 字符串,事件名
参数2:可选参数,按顺序传入回调函数的参数
返回值:该事件是否有监听
*/
//定义点菜事件
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
});
//定义埋单事件
restaurant.on('pay', function(num) {
console.log(num + "号桌, 埋单");
});
//1号桌,点菜
restaurant.emit('order', '红烧肉', 1);
//2号桌,点菜
restaurant.emit('order', '炒青菜', 2);
//3号桌,点菜
restaurant.emit('order', '土豆丝', 3);
//1号桌,埋单
restaurant.emit('pay', 1);
//2号桌,埋单
restaurant.emit('pay', 2);
//1号桌,埋单
restaurant.emit('pay', 3);
运行events-1.js:
lee@mypc ~/works/nodejs/study7 $ node events-1.js
1号桌,点菜:红烧肉
2号桌,点菜:炒青菜
3号桌,点菜:土豆丝
1号桌, 埋单
2号桌, 埋单
3号桌, 埋单
这是一个简单的示例,restaurant监听了两个事件"order"和"pay",顾客点菜和埋单时分别触发order和pay。
第二个events示例,假设点菜需要12个步骤,该怎么办?
events-2.js:
var events = require('events');
var restaurant = new events.EventEmitter();
/*
EventEmitter.emit(event, [arg1], [arg2], [...]) 触发指定事件
参数1:event 字符串,事件名
参数2:可选参数,按顺序传入回调函数的参数
返回值:该事件是否有监听
*/
var i=1;
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.emit('order', '红烧肉', 1);
因为order有12个步骤,所以我们添加了12个order事件。
运行结果:
lee@mypc ~/works/nodejs/study7 $ node events-2.js
(node) warning: possible EventEmitter memory leak detected. 11 order listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
at EventEmitter.addListener (events.js:239:17)
at Object.<anonymous> (/home/lee/works/nodejs/study7/events-2.js:66:12)
at Module._compile (module.js:425:26)
at Object.Module._extensions..js (module.js:432:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:313:12)
at Function.Module.runMain (module.js:457:10)
at startup (node.js:138:18)
at node.js:974:3
1号桌,点菜:红烧肉
点菜第1步
1号桌,点菜:红烧肉
点菜第2步
1号桌,点菜:红烧肉
点菜第3步
1号桌,点菜:红烧肉
点菜第4步
1号桌,点菜:红烧肉
点菜第5步
1号桌,点菜:红烧肉
点菜第6步
1号桌,点菜:红烧肉
点菜第7步
1号桌,点菜:红烧肉
点菜第8步
1号桌,点菜:红烧肉
点菜第9步
1号桌,点菜:红烧肉
点菜第10步
1号桌,点菜:红烧肉
点菜第11步
1号桌,点菜:红烧肉
点菜第12步
虽然成功完成了12个步骤,但是nodejs在添加第11个order时发出警告。这是因为events默认最大监听数量是10个(同一个事件,不同事件则没有限制)。
改进一下吧,events-3.js:
var events = require('events');
var restaurant = new events.EventEmitter();
restaurant.setMaxListeners(20);
/*
EventEmitter.emit(event, [arg1], [arg2], [...]) 触发指定事件
参数1:event 字符串,事件名
参数2:可选参数,按顺序传入回调函数的参数
返回值:该事件是否有监听
*/
var i=1;
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.on('order', function(name, num) {
console.log(num + "号桌,点菜:" + name );
console.log('点菜第'+(i++)+'步');
});
restaurant.emit('order', '红烧肉', 1);
再看运行结果:
lee@mypc ~/works/nodejs/study7 $ node events-3.js
1号桌,点菜:红烧肉
点菜第1步
1号桌,点菜:红烧肉
点菜第2步
1号桌,点菜:红烧肉
点菜第3步
1号桌,点菜:红烧肉
点菜第4步
1号桌,点菜:红烧肉
点菜第5步
1号桌,点菜:红烧肉
点菜第6步
1号桌,点菜:红烧肉
点菜第7步
1号桌,点菜:红烧肉
点菜第8步
1号桌,点菜:红烧肉
点菜第9步
1号桌,点菜:红烧肉
点菜第10步
1号桌,点菜:红烧肉
点菜第11步
1号桌,点菜:红烧肉
点菜第12步
Perfact !
时间: 2024-10-28 21:21:10