回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 全部 API 都支持回调函数。javascript
异步读取文件的回调函数:java
var fs = require("fs"); fs.readFile('input.txt', function (err, data) { if (err) return console.error(err); console.log(data.toString()); }); console.log("程序执行结束!");
Node.js 的每个 API 都是异步的node
Node.js 基本上全部的事件机制都是用设计模式中观察者模式实现。设计模式
Node.js 单线程相似 进入一个while(true)的事件循环,直到没有事件 观察者退出,每一个异步事件都生成一个事件观察者,若是有事件发生(观察者)就调用该回调函数。异步
有点相似于观察者模式,事件至关于一个主题(Subject),而全部注册到这个事件上的处理函数至关于观察者(Observer)。函数
var events = require('events');
var eventEmitter = new events.EventEmitter();
--------------------------------------------------------------------
// 方法1.采用handler函数 // 建立事件处理程序 var connectHandler = function connected() { console.log('链接成功'); // step 1 eventEmitter.emit('data_received'); // 这里触发 step 2 } // 绑定 connection 事件处理程序 eventEmitter.on('connection', connectHandler);
--------------------------------------------------------------------
// 方法2.采用匿名函数(或者箭头函数) // 使用匿名函数绑定 data_received 事件 eventEmitter.on('data_received', function(){ console.log('数据接收成功'); // step 2 }); // 触发 connection 事件 eventEmitter.emit('connection'); // 这里触发 step 1 console.log("程序执行完毕。"); // step 3
//event.js 文件 var events = require('events'); var emitter = new events.EventEmitter();
emitter.on('someEvent', function(arg1, arg2) { console.log('listener1', arg1, arg2); }); emitter.on('someEvent', function(arg1, arg2) { console.log('listener2', arg1, arg2); }); emitter.emit('someEvent', 'arg1 参数', 'arg2 参数');
当事件触发时,注册到这个事件的事件监听器被依次调用,事件参数做为回调函数参数传递。ui
$ node event.js
listener1 arg1 参数 arg2 参数
listener2 arg1 参数 arg2 参数
//event.js 文件 var EventEmitter = require('events').EventEmitter; var event = new EventEmitter(); event.on('some_event', function() { console.log('some_event 事件触发'); });
setTimeout(function() { event.emit('some_event'); }, 1000);
顺便提一个:间隔触发spa
setInterval ( ); --> clearInterval(timer); 线程
<script type="text/javascript"> window.onload = function () { var count = 0; var bt = document.getElementById("bt"); function show(){ document.getElementById("ant").innerHTML = count + 1; count = count +1; } var flag = setInterval(show, 1000); bt.onclick = function () { clearInterval(flag); } } </script>
一个综合性的例子:设计
var events = require('events'); var eventEmitter = new events.EventEmitter();
// (1) 定义监听回调方法 // 监听器 #1 var listener1 = function listener1() { console.log('监听器 listener1 执行。'); } // 监听器 #2 var listener2 = function listener2() { console.log('监听器 listener2 执行。'); }
// (2) 两种绑定监听器到事件上 // 绑定 connection 事件,处理函数为 listener1 eventEmitter.addListener('connection', listener1); // 绑定 connection 事件,处理函数为 listener2 eventEmitter.on('connection', listener2);
var eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection'); console.log(eventListeners + " 个监听器监听链接事件。");
// (3) 触发事件发生 // 处理 connection 事件 eventEmitter.emit('connection');
// (4) 去掉监听器 // 移除监绑定的 listener1 函数 eventEmitter.removeListener('connection', listener1); console.log("listener1 再也不受监听。"); // 触发链接事件 eventEmitter.emit('connection'); eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection'); console.log(eventListeners + " 个监听器监听链接事件。"); console.log("程序执行完毕。");
EventEmitter 定义了一个特殊的事件 error,它包含了错误的语义,遇到 异常的时候一般会触发 error 事件。
当 error 被触发时,EventEmitter 规定若是没有响 应的监听器,Node.js 会把它看成异常,退出程序并输出错误信息。
咱们通常要为会触发 error 事件的对象设置监听器,避免遇到错误后整个程序崩溃。例如:
var events = require('events'); var emitter = new events.EventEmitter(); emitter.emit('error');
大多数时候咱们不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。
为何要这样作呢?缘由有两点:
Person类自己会有多个有意义的对象,好比:xiaoming, lili, lucy。
但愿他们对同一个事件都会有相似的反应,好比老师喊报名,各自起来报本身姓名。
故,这里触发事件speak绑定在每个person身上。
以后,触发了xiaoming的神经;触发了lucy的神经。