浅谈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实现黑名单中间件设计
Jun 17 NodeJs
轻松创建nodejs服务器(5):事件处理程序
Dec 18 NodeJs
NodeJS创建基础应用并应用模板引擎
Apr 12 NodeJs
nodejs简单实现操作arduino
Sep 25 NodeJs
Nodejs高扩展性的模板引擎 functmpl简介
Feb 13 NodeJs
nodejs制作爬虫实现批量下载图片
May 19 NodeJs
NodeJS实现图片上传代码(Express)
Jun 30 NodeJs
nodejs 子进程正确的打开方式
Jul 03 NodeJs
nodejs中解决异步嵌套循环和循环嵌套异步的问题
Jul 12 NodeJs
nodejs更改项目端口号的方法
May 13 NodeJs
nodejs中request库使用HTTPS代理的方法
Apr 30 NodeJs
图解NodeJS实现登录注册功能
Sep 16 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中使用file_get_contents抓取网页中文乱码问题解决方法
2014/12/17 PHP
PHP统计数值数组中出现频率最多的10个数字的方法
2015/04/20 PHP
通过javascript设置css属性的代码
2009/12/28 Javascript
jQuery 性能优化手册 推荐
2010/02/23 Javascript
javascript判断两个IP地址是否在同一个网段的实现思路
2013/12/13 Javascript
js与jquery获取父级元素,子级元素,兄弟元素的实现方法
2014/01/09 Javascript
基于JQuery实现的Select级联
2014/01/27 Javascript
最新最热最实用的15个jQuery插件汇总
2015/07/05 Javascript
AngularJS 使用 UI Router 实现表单向导
2016/01/29 Javascript
JS基于递归实现倒计时效果的方法
2016/11/26 Javascript
jQuery基于Ajax方式提交表单功能示例
2017/02/10 Javascript
10个经典的网页鼠标特效代码
2018/01/09 Javascript
vue实现裁切图片同时实现放大、缩小、旋转功能
2018/03/02 Javascript
jQuery简单实现的HTML页面文本框模糊匹配查询功能完整示例
2018/05/09 jQuery
angular5 子组件监听父组件传入值的变化方法
2018/09/30 Javascript
vue调试工具vue-devtools安装及使用方法
2018/11/07 Javascript
让Vue响应Map或Set的变化操作
2020/11/11 Javascript
[03:40]DOTA2亚洲邀请赛小组赛第二日 赛事回顾
2015/01/31 DOTA
[00:12]2018DOTA2亚洲邀请赛 Somnus丶M出阵单挑
2018/04/06 DOTA
Python使用Paramiko模块编写脚本进行远程服务器操作
2016/05/05 Python
关于numpy中np.nonzero()函数用法的详解
2017/02/07 Python
Python搭建FTP服务器的方法示例
2018/01/19 Python
修复CentOS7升级Python到3.6版本后yum不能正确使用的解决方法
2018/01/26 Python
Python简单计算文件MD5值的方法示例
2018/04/11 Python
Python发送邮件功能示例【使用QQ邮箱】
2018/12/04 Python
python 列表输出重复值以及对应的角标方法
2019/06/11 Python
快速解决pymongo操作mongodb的时区问题
2020/12/05 Python
python 调用Google翻译接口的方法
2020/12/09 Python
JD Sports西班牙:英国领先的运动服装公司
2020/01/06 全球购物
财务人员个人工作总结
2015/02/27 职场文书
消防验收申请报告
2015/05/15 职场文书
单位证明范文
2015/06/18 职场文书
《夜莺的歌声》教学反思
2016/02/22 职场文书
正能量励志演讲稿三分钟(范文)
2019/07/11 职场文书
web前端之css水平居中代码解析
2021/05/20 HTML / CSS
python flask开发的简单基金查询工具
2021/06/02 Python