Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JS 和 Node.js 中的“事件驱动”是什么意思?[每日前端夜话0x106]

JS 和 Node.js 中的“事件驱动”是什么意思?[每日前端夜话0x106]

作者头像
疯狂的技术宅
发布于 2020-01-14 09:25:57
发布于 2020-01-14 09:25:57
9.3K00
代码可运行
举报
文章被收录于专栏:京程一灯京程一灯
运行总次数:0
代码可运行

翻译:疯狂的技术宅

作者:Valentino Gagliardi

来源:valentinog.com

事件驱动和发布-订阅

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

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

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

What means "event-driven" in JavaScript and Node.js?

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

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

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

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

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

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

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!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 【https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLButtonElement】类型的元素,并且与所有 HTML 元素一样,它们都连接到 EventTarget —— 每个 HTML 元素的共同祖先。

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

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

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

浏览器中的主题和观察者

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

使用 JavaScript 选择一个 HTML 元素:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const btn = document.getElementById('subscribe');

并使用 addEventListener 注册侦听器

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const btn = document.getElementById('subscribe');
btn.addEventListener("click", function () {
    console.log("Button clicked");
});

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

回顾一下:

HTML 元素事件发送器

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!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 服务器:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 有两种基本方法:onemit

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const btn = document.getElementById('subscribe');
btn.addEventListener("click", function () {
    console.log("Button clicked");
});

相反,在 Node.js 中有 on

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// omit
server.on("listening", () => {
  console.log("Server listening!");
});
// omit

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 的库。【http://reactivex.io/】

Redux 是 JavaScript 中发布-订阅模式的实现。这是一个非常好的事件发送器,其中状态的更改会被分发给所有监听的观察者。【https://www.valentinog.com/blog/redux/】

现代浏览器附带 Intersection Observer API,这是观察者模式的另一个例子。【https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API】

Socket.IO 是一个库,大量使用了事件。【https://www.valentinog.com/blog/socket-react/#The_WebSocket_protocol_Nodejs_and_SocketIO】

总结

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

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

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

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

原文:https://www.valentinog.com/blog/event/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端先锋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
在现代 JavaScript 中编写异步任务[每日前端夜话0xDD]
在本文中,我们将探讨过去异步执行的 JavaScript 的演变,以及它是怎样改变我们编写代码的方式的。我们将从最早的 Web 开发开始,一直到现代异步模式。
疯狂的技术宅
2019/11/03
3K0
如何正确使用Node.js事件[每日前端夜话0x4B]
事件驱动的编程变得流行之前,在程序内部进行通信的标准方法非常简单:如果一个组件想要向另外一个发送消息,只是显式地调用了那个组件上的方法。但是在 react 中用的却是事件驱动而不是调用。
疯狂的技术宅
2019/04/23
3.9K0
如何正确使用Node.js事件[每日前端夜话0x4B]
Node.js 的 EventEmitter 事件处理详解
在本教程中我们学习 Node.js 的原生 EvenEmitter 类。学完后你将了解事件、怎样使用 EvenEmitter 以及如何在程序中利用事件。另外还会学习 EventEmitter 类从其他本地模块扩展的内容,并通过一些例子了解背后的原理。
疯狂的技术宅
2020/11/03
1.9K0
Node.js 事件循环
Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。
陈不成i
2021/07/09
3.9K0
深入学习 Node.js EventEmitter
观察者模式,它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新自己。
阿宝哥
2019/11/06
1.2K0
深入学习 Node.js EventEmitter
Node.js 回调函数和事件循环
1. node.js 回调函数 node.js 的异步编程思想最直接的体现就是回调,在node中大量使用了回调函数,所有的API都支持回调函数,回调函数一般作为最后一个参数出现,正因为这样node在执行代码的时候就没有阻塞或者等待的操作,提高了node的性能,可以处理大量的并发请求。 function f1(name, age, callback){} function f2(name, callback, callback2){} 阻塞代码实例 创建一个文件input.txt内容如下: 这是一个阻
执行上下文
2022/07/26
3.4K0
Node.js 回调函数和事件循环
node.js 事件循环
  node.js是单线程的应用程序,但是他可能通过event和callback来支持并发。所有的node.js都是单线程的,也是异步的,他们使用调用异步函数来维持高并发。Node使用观察者模式。Node的线程会保持一个事件循环,当有任务完成时,他会触发相应的事件,通知事件监听函数执行。      事件驱动程序      node.js大量的使用事件,这也是和其他相同技术相比更快的原因。当Node被启动时,初始他的变量,和声明方法,而后等待事件的发生。      在一个事件驱动应用程序内,一般会有一个主要的
lpxxn
2018/01/31
3.3K0
node.js  事件循环
Node.js 知名框架 Express Koa 都在使用的 Events 模块你了解吗?
在 Node.js 中一个很重要的模块 Events(EventEmitter 事件触发器),也称为发布/订阅模式,为什么说它重要,因为在 Node.js 中绝大多数模块都依赖于此,例如 Net、HTTP、FS、Stream 等,除了这些系统模块比较知名的 Express、Koa 框架中也能看到 EventEmitter 的踪迹。
五月君
2019/11/06
2.2K0
Node.js原理
概述 Node.js是什么 Node 是一个服务器端 JavaScript 解释器,用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞I/O 模型而得以轻量和高效,非常适合在分布式设备上运行数据密集型的实时应用。 Node.js 是一个可以让 JavaScript 运行在浏览器之外的平台。它实现了诸如文件系统、模块、包、操作系统 API、网络通信等 Core JavaScript 没有或者不完善的功能。历史上将 JavaScript移植到浏览器外的计划不止一个,但Node.
xiangzhihong
2018/01/26
3.2K0
为什么要用 Node.js?[每日前端夜话0x77]
JavaScript 的日益发展带来了很多变化,当今的 Web 开发面貌已经变得截然不同。在几年前是很难想象在服务器上运行 JavaScript 的。
疯狂的技术宅
2019/06/02
2.9K0
如何优雅的实现消息通信?
作为一名 Web 开发者,在日常工作中,经常都会遇到消息通信的场景。比如实现组件间通信、实现插件间通信、实现不同的系统间通信。那么针对这些场景,我们应该怎么实现消息通信呢?本文阿宝哥将带大家一起来学习如何优雅的实现消息通信。
阿宝哥
2020/08/27
1.7K0
如何优雅的实现消息通信?
JavaScript错误处理完全指南
本文最初发布于 valentinog.com 网站,经原作者授权由 InfoQ 中文站翻译并分享。
深度学习与Python
2020/09/23
5.7K0
JavaScript错误处理完全指南
Node.js中常用的设计模式有哪些?
设计模式是由经验丰富的程序员在日积月累中抽象出的用以解决通用问题的可复用解决方案,它提供了标准化的代码设计方案提升开发体验。Node.js 作为一款用来构建可扩展高性能应用的流行平台,自然也遵循设计模式解决通用问题。本文中,我们将讨论 Node.js 中设计模式的重要性并提供一些代码示例。
葡萄城控件
2023/10/23
4740
Node.js中常用的设计模式有哪些?
15 个常见的 Node.js 面试问题及答案
临阵磨枪,不快也光。对于成功的编程面试来说,准备和知识面一样重要。准备使你有信心参加面试,而不用担心莫名的紧张情绪。如果第一次参加编程面试,这一点尤其重要。
coder_koala
2021/03/09
2.1K0
一文学会 Node.js 中的流[每日前端夜话0xF4]
用 Dominic Tarr 的话来说:“流是 Node 中最好的,也是最容易被误解的想法。”即使是 Redux 的创建者和 React.js 的核心团队成员 Dan Abramov 也害怕 Node 流。
疯狂的技术宅
2019/12/11
2.6K0
JS事件流
HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件、页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件。想要知道这些事件是在什么时候进行调用的,就需要了解一下“事件流”的概念。
前端逗逗飞
2021/04/30
9.2K0
JS事件流
深入浅出Node.js
2.模块定义:提供exports对象用于导出当前模块的方法或者变量,并且是唯一导出的出口
硬核项目经理
2019/08/06
1.4K0
深入解析Node.js:V8引擎、事件驱动和非阻塞式I/O
🎉欢迎来到架构设计专栏~探索Java中的静态变量与实例变量深入解析Node.js:V8引擎、事件驱动和非阻塞式I/O
IT_陈寒
2023/12/14
3880
深入解析Node.js:V8引擎、事件驱动和非阻塞式I/O
【读书笔记】《深入浅出 Node.js》
[《深入浅出 Node.js》] 读书笔记。 # 缘起 最初的目标是写一个基于事件驱动、非阻塞 I/O 的 Web 服务器。考虑高性能、符合事件驱动、没有历史包袱选择了 JavaScript。 # 特点 异步 I/O 事件与回调函数 事件优势:轻量级、松耦合、只关注事务点 单线程 优点 无需像多线程在意状态同步问题,没有死锁的存在 无线程上下文交换带来的性能上的开销 弱势 无法利用多核 CPU 错误会引起整个应用退出,应用的健壮性值得考验 大量计算占用 CPU 导致无法继续调用异步 I/O Node
Cellinlab
2023/05/17
9440
【读书笔记】《深入浅出 Node.js》
前端Node.js面试题
Node.js 是一个开源与跨平台的 JavaScript 运行时环境。在浏览器外运行 V8 JavaScript 引擎(Google Chrome 的内核),利用事件驱动、非阻塞和异步输入输出模型等技术提高性能。我们可以理解为:Node.js 就是一个服务器端的、非阻塞式I/O的、事件驱动的JavaScript运行环境。
xiangzhihong
2021/12/30
1.6K0
前端Node.js面试题
相关推荐
在现代 JavaScript 中编写异步任务[每日前端夜话0xDD]
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验