回调函数

回调函数在完成任务后就会被调用,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的更多相关文章

  1. 浅析Node.js的Event Loop

    目录 浅析Node.js的Event Loop 引出问题 Node.js的基本架构 Libuv Event Loop Event Loop Phases Overview Poll Phase The ...

  2. 定时器setTimeout()和Node.js的Event Loop

    一.定时器 setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是说,尽可能早得执行.它在"任务队列"的尾部添加一个事件,因此要等到同步任务和 ...

  3. Node.js的process.nextTick(callback)理解

    Node.js是单线程的,基于事件循环,非阻塞 IO的.事件循环中使用一个事件队列,在每个时间点上,系统只会处理一个事件,即使电脑有多个CPU核心,也无法同时并行的处理多个事件.因此,node.js适 ...

  4. 理解 Node.js 的 Event loop

    问题 考察如下代码,脑回路中运行并输出结果: console.log("1"); setTimeout(function setTimeout1() { console.log(& ...

  5. Node.js学习 - Event Loop

    Node.js本身是单线程,但通过事件和回调支持并发,所以性能非常高. Node.js的每一个API都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发. 事件驱动程序 实例 var ev ...

  6. 【Node.js】Event Loop执行顺序详解

    本文基于node 0.10.22版本 关于EventLoop是什么,请看阮老师写的什么是EventLoop 本文讲述的是EventLoop中的执行顺序(着重讲setImmediate, setTime ...

  7. node.js 中回调函数callback(转载),说的很清楚,看一遍就理解了

    最近在看 express,满眼看去,到处是以函数作为参数的回调函数的使用.如果这个概念理解不了,nodejs.express 的代码就会看得一塌糊涂.比如: 复制代码 代码如下: app.use(fu ...

  8. [转]使用Node.js完成的第一个项目的实践总结

    本文转自:http://blog.csdn.net/yanghua_kobe/article/details/17199417 https://github.com/yanghua/FixedAsse ...

  9. Node.js 打造实时多人游戏框架

    在 Node.js 如火如荼发展的今天,我们已经可以用它来做各种各样的事情.前段时间UP主参加了极客松活动,在这次活动中我们意在做出一款让“低头族”能够更多交流的游戏,核心功能便是 Lan Party ...

随机推荐

  1. 预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)(转)

    用VC++ 2008 编写C语言程序,编译出现错误: 预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反) 解决方法: 建工程时 建立空项目 或者在项目设置里关闭预编 ...

  2. 解密gzip压缩的网页数据流(转)

    因为采集某个网页遇到问题,一直无法获取页面数据. 经过一番排查,发现该网站会检查客户端的Header信息,如果遇到不明确的Header信息就直接否定,返回0数据. 如果Header信息正确,就会返回经 ...

  3. 转: chrome64打开弹出窗flash的办法

    https://jingyan.baidu.com/article/380abd0a38f0411d90192c2e.html

  4. version-script 控制 so的符号输出

    http://blog.sina.com.cn/s/blog_493667730100csde.html https://stackoverflow.com/questions/8129782/ver ...

  5. [BetterExplained]书写是为了更好的思考

    我经常在走路和睡前总结所学过的内容,思考遗留的问题,一段时间的阅读和思考之后,一个总体的知识框架就会逐渐浮现在脑海中.然后我会将它书写下来,然而,我往往非常惊讶地发现,当我书写的时候,新的内容仍然源源 ...

  6. 关于redis性能问题分析和优化

    一.如何查看Redis性能 info命令输出的数据可以分为10个分类,分别是: server,clients,memory,persistence,stats,replication,cpu,comm ...

  7. 《Redis入门指南(第2版)》读后感

    今天刚刚将此书看完,现在还能记住一些内容,还有一些感慨感想,正好又想写点什么了就随便记录一下吧!也许灵感明天就消失了呢? 首先觉得作者非常的厉害,年纪轻轻的就写出了这么一本非常不错的书籍! 然后就是对 ...

  8. CSS3 选择器 基本选择器介绍

    CSS是一种用于屏幕上渲染html,xml等一种语言,CSS主要是在相应的元素中应用样式,来渲染相对应用的元素,那么这样我们选择相应的元素就很重要了,如何选择对应的元素,此时就需要我们所说的选择器.选 ...

  9. 使用RStudio远程连接MySQL

    环境: 远程机: linux + Mysql 本地机: Windows + RStudio 问题: 1. 远程机为内网机器,需要跳板机连接,没有公网ip,无法连接 解决方案:修改跳板机的iptable ...

  10. 常见Python爬虫工具总结

    常见Python爬虫工具总结 前言 以前写爬虫都是用requests包,虽然很好用,不过还是要封装一些header啊什么的,也没有用过无头浏览器,今天偶然接触了一下. 原因是在处理一个错误的时候,用到 ...