Node模块之Events模块(五)

IT实战联盟 2017-12-13 13:40:56 ⋅ 151 阅读
前提 Nodejs EventLoop
0.1 【堆】【栈】【队列】

堆栈队列

任何一种语言的运行环境都少不了【堆(heap)】【栈(Stack)】【队列 (queue) 】,JS也不例外。
JS的【临时变量以及调用时的形参】等等数据都是存储在【栈】中;
【堆】则是存储实际的【对象】,对象的【引用变量名(指针)】也是在【栈】;
而队列则是JS在实时运行环境中创建的【消息队列】或者【事件队列】。
JS是单线程,所以队列的实现让JS的异步处理有了可能性。

02 单线程、任务队列

尽信书不如无书,就喜欢这种有理有据的

摘录自【朴灵评注】JavaScript 运行机制详解:再谈Event Loop

为了避免复杂性,从一诞生,同一个时间只能做一件事。JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。
为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

异步执行的运行机制

(1)所有任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。系统把异步任务放到"任务队列"之中,然后继续执行后续的任务。
(3)一旦"执行栈"中的所有任务执行完毕,系统就会读取"任务队列"。如果这个时候,异步任务已经结束了等待状态,就会从"任务队列"进入执行栈,恢复执行。
(4)主线程不断重复上面的第三步。

上面这段初步地在说event loop。但是异步跟event loop其实没有关系。准确的讲,【event loop是实现异步的一种机制】

【上面提到的一系列的手段其实就是实现异步的方法,其中就包括event loop。以及轮询、事件等。】
【所谓轮询:就是你在收银台付钱之后,坐到位置上不停的问服务员你的菜做好了没。】
【所谓(事件):就是你在收银台付钱之后,你不用不停的问,饭菜做好了服务员会自己告诉你。】

【JavaScript运行环境的运行机制,不是JavaScript的运行机制。】

0.3 事件循环

首先我们看一下nodejs本质结构图

image.png

Node.js 通过 libuv 来处理与操作系统的交互,并且因此具备了【异步、非阻塞、事件驱动】的能力。Node.js 实际上是 Javascript 执行线程的单线程,真正的I/O 操作,底层 API 调用都是通过【多线程】执行的。

本质也就是:任务接收是单线程,任务执行是多线程。

那么也就是主要依靠【libuv】,那么本文主要介绍Nodejs事件模块,当然离不开原理,为何是这样?为何这么吊?为何又出现那么多回调函数?带着一些列问题搞明白了理论,至于代码,那也调用哪些大神写的API吧!

膜拜大神三秒钟

技术(艺术)源自生活、高于生活。对吧。

歪瓜仁真会玩

只要开始启动,那么这个姑娘就开始嗨起来了,其实我们事件循环也是这样的!从启动开始,就一直不停止的监听。

【论英文的重要性】

image.png

一图胜千言,但我还是就下图做个简单的梳理吧。我可不想被同为学渣的老铁们骂哈。

image.png

我们程序猿其实工作还是仅限于代码调用编写阶段,主要的核心在于理解内部原理,然后根据需求去编写(复制)代码。

讲个故事吧

JS单身狗(单线程)无异议,但它也是个贪心的黑心老板,在外边一直接活一直接活,根本无视
员工的死活,程序猿们为了改变世界(为了生存)不得不听产品经理的安排(程序猿心中的恶魔),
产品经理承上启下,一直分发任务(闲就不是代码狗了),而为了理想而奋战(别给我嘚瑟四点的晨曦,
老子刚下班)。世界越来越美好(为奋战的人祈祷安康)!

Nodejs中是怎么个情况,请看下图

event5.png

好了,结束了,接下来就是代码啦。

第一 Events模块概述

Events模块是Node对“发布/订阅”模式(publish/subscribe)的实现。一个对象通过这个模块,向另一个对象传递消息。

Node中的Event模块仅仅提供了一个对象: EventEmitter, EventEmitter 的核心就是事件触发与事件监听器功能的封装。

获取EventEmitter对象

//引用模块events, 点语法获取到EventEmitter var EventEmitter = require('events').EventEmitter; //初始化一个对象, 这个实例就是消息中心。 var emitter = new EventEmitter;
第二 EventEmitter 实例对象的方法

2.1 emitter.on(eventName, listener), 监听事件,如果触发就调用回调函数

1. eventName <String> | <Symbol>: 事件名称, 后边可以跟上函数; 2. listener <Function> : 回调函数;

2.2 emitter.emit(eventName[, ...args]), 根据eventName发送通知, 触发事件, 第一个参数为事件名称, 其余的参数会依次传入回调函数

以上两个方法的示例代码

var EventEmitter = require('events').EventEmitter; var emitter = new EventEmitter(); //监听函数1, 事件名为--fun1 emitter.on('fun1', function(){    console.log('触发函数1'); }); //定义有参数函数fun2, var fun2 = function(para){    console.log('触发函数2, 参数为' + para); }; //监听fun2 emitter.on('fun2', fun2); //触发事件名 emitter.emit('fun1'); //触发事件名并且传参数 emitter.emit('fun2', 'event');

打印结果为:

$ node 2on.js 触发函数1 触发函数2, 参数为event

2.3 emitter.once(eventName, listener), 类似on方法, 但回调函数只是执行一次

var EventEmitter = require('events').EventEmitter; var emitter = new EventEmitter(); emitter.once('oncefun', function(){    console.log('函数只执行一次'); }); emitter.emit('oncefun'); emitter.emit('oncefun'); console.log('--------') emitter.on('fun', function(){    console.log('函数'); }); emitter.emit('fun'); emitter.emit('fun');

执行的结果为:

$ node 3once.js 函数只执行一次 函数 函数

虽然触发多次oncefun, 但依然打印一次;与下边形成对比;,

2.4 emitter.addListener(eventName, listener)类似于emitter.on(eventName, listener)

2.5 emitter.removeListener(eventName, listener), 移除监听

详细见实例代码:

var EventEmitter = require('events').EventEmitter; var emitter = new EventEmitter(); //定义一个函数 var removeFun = function(){    console.log('输出结果'); } //以fun名称监听removeFun emitter.on('fun', removeFun); //每个30毫秒触发一次回调函数 setInterval(function(){    emitter.emit('fun'); }, 30); //200毫秒以后触发回调函数 setTimeout(function(){    emitter.removeListener('fun', removeFun); }, 200);

打印结果

$ node 5removeListener.js 输出结果 输出结果 输出结果 输出结果 输出结果 #光标停止
第三部分 更多API详见

语法名称觉得挺好的, 见名知意. 更多的语法就看Node官网吧 -__-

Event: 'newListener' Event: 'removeListener' EventEmitter.listenerCount(emitter, eventName) EventEmitter.defaultMaxListeners emitter.addListener(eventName, listener) emitter.emit(eventName[, ...args]) emitter.eventNames() emitter.getMaxListeners() emitter.listenerCount(eventName) emitter.listeners(eventName) emitter.on(eventName, listener) emitter.once(eventName, listener) emitter.prependListener(eventName, listener) emitter.prependOnceListener(eventName, listener) emitter.removeAllListeners([eventName]) emitter.removeListener(eventName, listener) emitter.setMaxListeners(n)

欢迎转载关注,后期会提供更多非基础内容,敬请期待。





全部评论: 0

    我有话说:

    Node模块fs模块(六)

    屏幕快照 2017-08-08 上午10.53.21.png 第一部分 概述 Node.js 提供一组类似UNIX(POSIX)标准的文件操作API,Node.js中操作文件的模块是fs(File

    Node 模块 util URL queryString path(八)

    第一部分 util util是一个Node.js核心模块,util模块设计的主要目的是为了满足Node内部API的需求。其中包括:格式化字符串、对象的序列化、实现对象继承等常用方法。要使用util

    Node模块(四)

    模块化分工、各司其职

    Node实战篇:Express--jade模板引擎(七)

    Jade(Pug) — Node Template Engine,一个高性能的模板引擎,专为 Node 而做......

    「轻阅读」聊一聊6种常用的架构设计模式(上)

      许多现代应用都需要在企业级规模上进行构建,有时甚至需要在互联网规模上进行构建。这些应用都需要满足可扩展性、可用性、安全性、可靠性和弹性需求。 在本文中,我将谈论一些设计模式,这些模式

    Node实战篇:使用joi来验证数据模型 (十)

    Joi 是 hapijs 自带的数据校验模块,他已经高度封装常用的校验功能,本文就是介绍如何优雅地使用 joi 对数据进行校验......

    Node实战篇:Express 中间件-body-parser()

    body-parser是什么?body-parser是一个HTTP请求体解析中间件,使用这个模块可以解析JS

    Node异步式I/O和异步式编程(三)

     Node.js 最大的特点就是异步式 I/O(或者非阻塞I/O)与事件紧密结合的编程模式。 第一部分: I/O 1.阻塞I/O与非阻塞I/O概念 1.1阻塞I/O(同步I/O) 线程在

    Node实战篇:阶段项目(九)

    项目整体预览 项目的github地址 界面逼格还行-_- 主要功能: 登陆; 退出; 所用的主要模块: express, 路由.静态文件.模块分工等; express-session, 采用

    Node&RabbitMQ系列 保证投递

      网上又很多确保消息100%投递相关的文章,但总的来说还是分为几种情况的 发送端如何确保发送到了交换机 消费端针对不同情况处理消息–后续再说 本文围绕发布者相关内容,目标  发布者消息确认【100%】  ma...

    Nodejs视频服务器 切片ffmpeg

    Node 视频服务器 切片ffmpeg

    运维监控软件 wgcloud 更新,v3.2.7 重构告警模块

    WGCLOUD,server端基于springboot开发,agent端使用go编写。支持高并发高性能,核心模块包括:服务器集群监控,ES集群状态监控,CPU监控,内存监控,数据监控,docker

    Nodejs实用技巧-Exceljs

    今天我们就在此介绍下exceljs的基本使用,应该可以满足我们大部分的需求。

    Nodejs神兽--Promise

    言必信,行必果。 没毛病,这就是Promise!

    SQL 模板神器

    SqlTemplate - MyBatis SqlTemplate - MyBatis 是sql模板引擎,主要解决动态拼接sql字符串 。原理是比较简单,把模板内容构建成完成的xml,这样

    Node实战篇:Express-session解析(八)

    Session和HTTP协议属于不同层面的事物,HTTP属于ISO七层模型的最高层应用层,前者Session不属于后者,前者HTTP是具体的动态页面技术来实现的,但同时它又是基于后者的。

    Node实战篇:Express路由(三)

    Express 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架,它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用。

    2018年8个技巧来构建更好的Node.js应用程序

    2018年8个技巧来构建更好的Node.js应用程序