浅谈JS和Nodejs中的事件驱动


Posted in NodeJs onMay 05, 2021

事件驱动和发布-订阅

事件驱动架构是建立在软件开发中一种通用模式上的,这种模式被称为发布-订阅或观察者模式。

在事件驱动架构中,至少有两个参与者:主题(subject)和观察者(observer)。

主题就像调频收音机一样,向有兴趣收听该主题所说内容的观察者进行广播。

观察者可能只有一个,也可能有一百个,这都没有关系,只要主题有一些要广播的消息就够了。

请记住,事件驱动、发布-订阅和观察者模式在实践中不是一回事,但在理想情况下,它们使用相同的方法:一个实体广播一条消息,其他实体侦听该消息。

发布-订阅模式和我一样老。在 1987 年左右开始理论化,而观察者模式则出现在 1994 年由“四人帮”所写的著作《设计模式》中。

事件驱动是怎样用在浏览器中的JavaScript的?

借助引擎,JavaScript可以运行在你的浏览器中。

最受欢迎的 JavaScript 引擎是 Google Chrome 和 Node.js所使用的V8,Firefox 的 SpiderMonkey 和 Safari/WebKit 使用的 JavaScriptCore。

基于供丰富的环境,JavaScript 引擎增强了语言,还提供了事件驱动的 JavaScript 平台。

实际上,浏览器中的 JavaScript 可以与html元素进行交互,这些html元素是事件发送器(event emitters),即能够发送事件的对象。

思考一下这个简单的例子,一个带有按钮的 HTML 文档:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>What means "event-driven" in JavaScript?</title>
</head>
<body>
<div>
    <button id="subscribe">SUBSCRIBE</button>
</div>
</body>
</html>

如果没有 JavaScript,则这个按钮将毫无生命。现在 HTML 按钮是HTMLButtonElement类型的元素,并且与所有 HTML 元素一样,它们都连接到EventTarget—— 每个 HTML 元素的共同祖先。

浏览器中的事件目标是能够发出事件的对象:它们是观察者模式中的主题。

有点混乱?请记住:主题是 FM 广播,所以任何 HTML 元素都像是广电台。

一会儿,你将看到谁是观察者。

浏览器中的主题和观察者

如果 HTML 元素是主题,那么谁是观察者?任何注册为侦听器的 JavaScript函数都可以对浏览器中的事件做出反应。

使用 JavaScript 选择一个 HTML 元素:

const btn = document.getElementById('subscribe');

并使用 addEventListener注册侦听器:

const btn = document.getElementById('subscribe');
btn.addEventListener("click", function () {
    console.log("Button clicked");
});

这里的“click”是事件,按钮是主题,或者是发送器,函数是侦听器,或者是观察者。

回顾一下:

HTML 元素是事件发送器。

JavaScript 中注册为侦听器的函数是观察者。

所有这些组件构成了“一个小小的事件驱动的体系结构。要测试代码请保存下面的 HTML 内容到文件(或在 Codepen 上尝试),请单击按钮,然后查看浏览器的控制台:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>What means "event-driven" in JavaScript?</title>
</head>
<body>
<div>
    <button id="subscribe">SUBSCRIBE</button>
</div>
</body>
<script>
    const btn = document.getElementById('subscribe');
    btn.addEventListener("click", function () {
        console.log("Button clicked");
    });
</script>
</html>

在下一部分中,你将看到用于 Node.js的相同概念。

事件驱动如何用于 Node.js?

Node.js是用于基于 V8 引擎的运行在浏览器之外(命令行工具和服务器端)的 JavaScript 环境。

你在 Node.js 中所做的大部分工作都是基于事件的。总会有一个发送器对象,一些观察者在监听消息。

在 Node.js 中,没有任何 HTML 元素,因此大多数事件都来自进程、与网络的交互、文件等。

Node.js 中的每个事件发送器都有一个名为on的方法,该方法至少需要两个参数:

  • 要侦听的事件的名称
  • 监听器函数

让我们举一个实际的例子。看一下这个简单的 Node.js 服务器:

const net = require("net");
const server = net.createServer().listen(8081, "127.0.0.1");
server.on("listening", function () {
  console.log("Server listening!");
});
server.on("connection", function (socket) {
  console.log("Client connected!");
  socket.end("Hello client!");
});

这段代码创建了一个监听本地主机端口 8081 的服务器。在server 对象上,我们调用 on 方法来注册两个侦听器函数。

服务器启动后立即触发listening事件,而客户端连接到 127.0.0.1:8081 时将触发connection 事件(尝试一下!)。

在此示例中,server是事件发送器,主题。另一方面,侦听器函数是观察者。

但是那些on方法从哪里来的呢?

了解 EventEmitter

Node.js 中的所有事件驱动模块都扩展了一个名为EventEmitter的根类。在我们之前的例子中,来自 net 模块的网络服务器就使用了 EventEmitter。

Node.js 中的EventEmitter有两种基本方法:on和emit。

如果你想要与浏览器对应,那么可以把EventEmitter看作是能够发出事件的任何一种 HTML 元素。

要在浏览器中侦听事件,请在主题对象上调用addEventListener:

const btn = document.getElementById('subscribe');
btn.addEventListener("click", function () {
    console.log("Button clicked");
});

相反,在 Node.js 中有on:

// omit
server.on("listening", () => {
  console.log("Server listening!");
});
// omit

准确地说,Eve​​ntEmitter上还有一个addListener方法。on是它的别名。

EventEmitter还有一个emit方法,在你广播自定义事件(消息)时很有用。

如果要使用EventEmitter,请从 “events” 模块中导入并发出事件:

const EventEmitter = require("events");
const emitter = new EventEmitter();
emitter.on("customEvent", () => console.log("Got event!"));
emitter.emit("customEvent");

用 Node.js 运行代码,你将在控制台中看到 “Got event”。

JavaScript 中有关观察者/发布-订阅的其他示例

JavaScript 没有对观察者对象的原生支持,但是有人建议将其添加到语言中。

RxJS是一个将观察者模式引入 JavaScript 的库。

Redux是 JavaScript 中发布-订阅模式的实现。 这是一个非常好的事件发送器,其中状态的更改会被分发给所有监听的观察者。

现代浏览器附带Intersection Observer API,这是观察者模式的另一个例子。

Socket.IO是一个库,大量使用了事件。

总结

希望你从这篇文章中学到新的东西。你学到了很多术语,但最终都归结为大约 30 年前发明的模式:发布-订阅。

这种模式,也称为观察者,是我们今天在 JavaScript 和 Node.js 中所使用的事件驱动架构的基础。

再次强调,事件驱动、发布-订阅和观察者的模式并非完全相同:事件驱动的体系结构建立在发布-订阅之上,观察者模式比 DOM 和 Node.js 事件更丰富。

但他们都是属于同一个家庭的成员。

以上就是浅谈JS和Nodejs中的事件驱动的详细内容,更多关于JS和Nodejs中的事件驱动的资料请关注三水点靠木其它相关文章!

NodeJs 相关文章推荐
轻松创建nodejs服务器(6):作出响应
Dec 18 NodeJs
轻松创建nodejs服务器(10):处理上传图片
Dec 18 NodeJs
nodejs 整合kindEditor实现图片上传
Feb 03 NodeJs
浅谈Nodejs应用主文件index.js
Aug 28 NodeJs
Nodejs进阶:基于express+multer的文件上传实例
Nov 21 NodeJs
nodejs操作mysql实现增删改查的实例
May 28 NodeJs
Linux Centos7.2下安装nodejs&amp;npm配置全局路径的教程
May 15 NodeJs
NodeJS 中Stream 的基本使用
Jul 30 NodeJs
NodeJs生成sitemap站点地图的方法示例
Jun 11 NodeJs
nodejs对mongodb数据库的增加修删该查实例代码
Jan 05 NodeJs
Nodejs环境实现socket通信过程解析
Jul 03 NodeJs
windows如何把已安装的nodejs高版本降级为低版本(图文教程)
Dec 14 NodeJs
ubuntu系统下使用pm2设置nodejs开机自启动的方法
May 12 #NodeJs
NodeJS和浏览器中this关键字的不同之处
Mar 03 #NodeJs
nodejs处理tcp连接的核心流程
Feb 26 #NodeJs
Nodejs 数组的队列以及forEach的应用详解
Feb 25 #NodeJs
一文秒懂nodejs中的异步编程
Jan 28 #NodeJs
在nodejs中创建child process的方法
Jan 26 #NodeJs
nodejs中使用worker_threads来创建新的线程的方法
Jan 22 #NodeJs
You might like
如何使用PHP中的字符串函数
2006/10/09 PHP
Linux下php5.4启动脚本
2014/08/03 PHP
php文件上传简单实现方法
2015/01/24 PHP
ThinkPHP自定义函数解决模板标签加减运算的方法
2015/07/03 PHP
ASP.NET jQuery 实例16 通过控件CustomValidator验证RadioButtonList
2012/02/03 Javascript
JS中 用户登录系统的解决办法
2013/04/15 Javascript
jquery实现鼠标拖动图片效果示例代码
2014/01/09 Javascript
js获取和设置属性的方法
2014/02/20 Javascript
JQuery插件ajaxfileupload.js异步上传文件实例
2015/05/19 Javascript
Bootstrap每天必学之表单
2015/11/23 Javascript
浅谈原型对象的常用开发模式
2017/07/22 Javascript
Angular 4.0学习教程之架构详解
2017/09/12 Javascript
javascript高级模块化require.js的具体使用方法
2017/10/31 Javascript
解决layui页面按钮点击无反应,也不报错的问题
2019/09/29 Javascript
bootstrap实现嵌套模态框的实例代码
2020/01/10 Javascript
js实现圆形显示鼠标单击位置
2020/02/11 Javascript
[07:31]DOTA2卡尔工作室 英雄介绍主宰篇
2013/06/25 DOTA
Python Web框架Pylons中使用MongoDB的例子
2013/12/03 Python
python实现带验证码网站的自动登陆实现代码
2015/01/12 Python
python 用正则表达式筛选文本信息的实例
2018/06/05 Python
使用Anaconda3建立虚拟独立的python2.7环境方法
2018/06/11 Python
python实现任意位置文件分割的实例
2018/12/14 Python
Python 实现交换矩阵的行示例
2019/06/26 Python
pyinstaller参数介绍以及总结详解
2019/07/12 Python
Python 转换文本编码实现解析
2019/08/27 Python
Python安装whl文件过程图解
2020/02/18 Python
HTML5的Video标签有部分MP4无法播放的问题解析(多图)
2017/08/18 HTML / CSS
美国知名的家庭连锁百货商店:Boscov’s
2017/07/27 全球购物
美国隐形眼镜零售商:LensPure
2019/03/10 全球购物
饿了么订餐官网:外卖、网上订餐
2019/06/28 全球购物
快餐店的创业计划书范文
2014/01/29 职场文书
大学生社会实践评语
2014/04/25 职场文书
2014年师德师风学习材料
2014/05/16 职场文书
校庆标语集锦
2014/06/25 职场文书
大学活动总结模板
2014/07/10 职场文书
Python OpenCV实现图像模板匹配详解
2022/04/07 Python