[Node.js] 04 - Event and Callback
回调函数
回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数。
异步读取文件的回调函数:
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.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 参数');
当事件触发时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递。
$ 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);
顺便提一个:间隔触发
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("程序执行完毕。");
Error 事件
EventEmitter 定义了一个特殊的事件 error,它包含了错误的语义,遇到 异常的时候通常会触发 error 事件。
当 error 被触发时,EventEmitter 规定如果没有响 应的监听器,Node.js 会把它当作异常,退出程序并输出错误信息。
我们一般要为会触发 error 事件的对象设置监听器,避免遇到错误后整个程序崩溃。例如:
var events = require('events');
var emitter = new events.EventEmitter();
emitter.emit('error');
继承 EventEmitter
大多数时候我们不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。
为什么要这样做呢?原因有两点:
- 首先,具有某个实体功能的对象实现事件符合语义, 事件的监听和发生应该是一个对象的方法。
- 其次 JavaScript 的对象机制是基于原型的,支持 部分多重继承,继承 EventEmitter 不会打乱对象原有的继承关系。
Person类本身会有多个有意义的对象,比如:xiaoming, lili, lucy。

希望他们对同一个事件都会有类似的反应,比如老师喊报名,各自起来报自己姓名。
故,这里触发事件speak绑定在每一个person身上。
之后,触发了xiaoming的神经;触发了lucy的神经。

[Node.js] 04 - Event and Callback的更多相关文章
- 浅析Node.js的Event Loop
目录 浅析Node.js的Event Loop 引出问题 Node.js的基本架构 Libuv Event Loop Event Loop Phases Overview Poll Phase The ...
- 定时器setTimeout()和Node.js的Event Loop
一.定时器 setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是说,尽可能早得执行.它在"任务队列"的尾部添加一个事件,因此要等到同步任务和 ...
- Node.js的process.nextTick(callback)理解
Node.js是单线程的,基于事件循环,非阻塞 IO的.事件循环中使用一个事件队列,在每个时间点上,系统只会处理一个事件,即使电脑有多个CPU核心,也无法同时并行的处理多个事件.因此,node.js适 ...
- 理解 Node.js 的 Event loop
问题 考察如下代码,脑回路中运行并输出结果: console.log("1"); setTimeout(function setTimeout1() { console.log(& ...
- Node.js学习 - Event Loop
Node.js本身是单线程,但通过事件和回调支持并发,所以性能非常高. Node.js的每一个API都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发. 事件驱动程序 实例 var ev ...
- 【Node.js】Event Loop执行顺序详解
本文基于node 0.10.22版本 关于EventLoop是什么,请看阮老师写的什么是EventLoop 本文讲述的是EventLoop中的执行顺序(着重讲setImmediate, setTime ...
- node.js 中回调函数callback(转载),说的很清楚,看一遍就理解了
最近在看 express,满眼看去,到处是以函数作为参数的回调函数的使用.如果这个概念理解不了,nodejs.express 的代码就会看得一塌糊涂.比如: 复制代码 代码如下: app.use(fu ...
- [转]使用Node.js完成的第一个项目的实践总结
本文转自:http://blog.csdn.net/yanghua_kobe/article/details/17199417 https://github.com/yanghua/FixedAsse ...
- Node.js 打造实时多人游戏框架
在 Node.js 如火如荼发展的今天,我们已经可以用它来做各种各样的事情.前段时间UP主参加了极客松活动,在这次活动中我们意在做出一款让“低头族”能够更多交流的游戏,核心功能便是 Lan Party ...
随机推荐
- 前端框架React Js入门教程【精】
现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领 ...
- Win8下枚举任意进程的句柄表。。。(VB6 Code)
添加一个Command1.一个List1,代码: Private Type PROCESS_HANDLE_TABLE_ENTRY_INFO HandleValue As Long HandleCoun ...
- 详解Paint的setColorFilter(ColorFilter filter)
一.简介 setColorFilter(ColorFilter filter) 设置颜色过滤,这个方法需要我们传入一个ColorFilter参数同样也会返回一个ColorFilter实例.我们在set ...
- 9.7 dubbo心跳机制
dubbo的心跳机制: 目的:检测provider与consumer之间的connection连接是不是还连接着,如果连接断了,需要作出相应的处理. 原理: provider:dubbo的心跳默认是在 ...
- C# SpinLock实现
关于SpinLock自旋锁网上已经有很多说明,这里也copy了一部分,我这里主要关注微软的实现,学习人家的实现方式. 如果由于垃圾回收,基于对象的锁对象开销太高,可以使用SpinLock结构..NET ...
- 从源码编译InfluxDB
操作系统 : CentOS7.3.1611_x64 go语言版本:1.8.3 linux/amd64 InfluxDB版本:1.1.0 go语言安装参考: http://www.cnblogs.com ...
- ASP.NET MVC 4 简介
介绍 使用Visual Studio 2010开发的话,首先需要安装MVC4,可以参考另一篇文章 进行安装. ASP.NET MVC 运行流程 (Clinet) Http Request 客户端发起 ...
- winform的combox下拉框绑定数据源
List<Site> list = new List<Site>(); foreach (DataRow srcDr in srcDt.Rows) { list.Add(new ...
- 自建Kubernetes logtail日志采集客户端安装方式
自建Kubernetes安装方式 前提条件 Kubernetes集群版本1.8及以上. 已经安装Helm命令,版本2.6.4及以上. 安装步骤 在日志服务控制台创建一个Project,Project名 ...
- mechanize (1)
最近看的关于网络爬虫和模拟登陆的资料,发现有这样一个包 mechanize ['mekə.naɪz]又称为机械化的意思,确实文如其意,确实有自动化的意思. mechanize.Browser and ...