回调函数

回调函数在完成任务后就会被调用,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. .w调用action

    有两种方法发送Action请求,分别是sendBizRequest和sendBizRequest2,前者返回xml格式的参数,后者提供了返回json或者xml格式的参数的能力. 1.sendBizRe ...

  2. 15个优秀的开源项目,让你轻松应对Android开发

    一.huabanDemo-android 应用material design版的花瓣网App 项目地址 https://github.com/LiCola/huabanDemo 二.创建视差效果引导页 ...

  3. Java LinkedList工作原理及实现

    1. 概述 以双向链表实现.链表无容量限制,但双向链表本身使用了更多空间,也需要额外的链表指针操作. 按下标访问元素—get(i)/set(i,e) 要悲剧的遍历链表将指针移动到位(如果i>数组 ...

  4. 【转】《iOS7 by Tutorials》系列:iOS7的设计精髓(上)

    简介: 本文翻译自<iOS7 by Tutorials>一书的第一章“Designing for iOS 7”,主要从程序员角度介绍了iOS7的新设计理念,堪称神作!本文翻译仅作学习交流之 ...

  5. CSS中的偏僻知识点

    一.css中的calc 在CSS中有calc属性用于尺寸的计算,可以让百分比和像素值进行运算. div {width : calc(100% - 30px);} 为了兼容性 /*Firefox*/ - ...

  6. LaTeX 中使两张表格并排

    在使用 LaTeX写论文或者画海报的时候,希望两张较小的表格可以并排,(一般情况的LaTeX插入两张图片是上下布局的) 查找了一下,相关的例子如下: \begin{minipage}{\textwid ...

  7. 20151028整理罗列某种开发所包括对技术(技术栈),“较为全面”地表述各种技术大系的图表:系统开发技术栈图、Web前端技术栈图、数据库技术栈图、.NET技术栈图

    ———————————— 我的软件开发生涯 (10年开发经验总结和爆栈人生) 爆栈人生 现在流行说全栈.每种开发都有其相关的技术.您是否觉得难以罗列某种开发所包括对技术(技术栈)呢?   您是否想过: ...

  8. 基于Ubuntu部署 memcached 服务

    系统要求:Ubuntu 16.04.1 LTS 64 位操作系统 安装并启动 memcached 服务 安装 memcached 使用apt-get安装 memcached sudo apt-get ...

  9. [剑指Offer]5.二维数组中的查找

    题目 在一个二维数组中,每一行都依照从左到右递增的顺序排序,每一列都依照从上到下递增的顺序排序.请完毕一个函数,输入这种一个二维数组和一个整数.推断数组中是否含有该整数. 思路 [算法系列之三十三]杨 ...

  10. 使用Python解析JSON详解

    为大家介绍如何使用 Python 语言来编码和解码 JSON 对象. JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写. JSON 函数 ...