浅谈JS和Nodejs中的事件驱动

事件驱动和发布-订阅

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

在事件驱动架构中,至少有两个参与者:主题(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中的事件驱动的资料请关注我们其它相关文章!

时间: 2021-05-03

js事件驱动机制 浏览器兼容处理方法

3.1. 事件是如何产生的 * 第一种情况,用户对网页做了某些操作,比如,点击了一个按钮,产生点击事件. 第二种情况,用户没有对网页做操作,也可能产生事件,比如浏览器已经将整个页面加载完毕,会产生加载完成事件.当事件产生以后,浏览器会查找产生事件的节点有没有绑订相应的事件处理代码.如果有,则调用该代码来处理.如果没有,会继续向上查找父节点,有没有对应的事件处理代码(事件冒泡). 3.2. 绑订事件处理代码 ** 1) 绑订事件处理代码到html标记乊上 比如: <a id="a1"

深入理解javaScript中的事件驱动

javascript中的事件驱动是通过 鼠标或热键 的动作引发的  主要事件如下:1.鼠标单击事件 onclick   如:( <input type="button" value="鼠标单击" onclick="执行语句.处理" />) 通常用于如下控件:button 按钮对象checkbox 复选框或检查列表 --配合onclick单击事件,通常用于全选效果radio 单选按纽reset 重置按钮submit提交按钮 2.内容改变

快速掌握Node.js事件驱动模型

一.传统线程网络模型 在了解Node.js事件驱动模型之前,我们先了解一下传统的线程网络模型,请求进入web服务器(IIS.Apache)之后,会在线程池中分配一个线程来线性同步完成请求处理,直到请求处理完成并发出响应,结束之后线程池回收. 这就会就会带来以下几个问题 : 1.由于线程池中线程个数有限,对于频繁请求时,就会出现等待,严重的甚至会把服务器挂掉 2.对于高并发的时候,为了防止出现脏数据就会使用锁来解决,一些I/O事务可能消耗很长得时间,这样就会出现一些线程等待,效率低下 二.事件驱动

JScript面向事件驱动的编程

世间万物,千变万化,面向对象的编程亦是对现实社会的模拟,而JavaScript是一种基于对象并且很接近面向对象编程的编程语言,而我们web设计师/程序员跟JavaScript打交道亦要直面JavaScript才能够把网页写得更加丰富多彩.在此先搞清楚一点就是:JavaScript并不仅仅用在Web上,它可以用在许多领域,当然我这里讨论的更多的是JavaScript在Web上的应用,并且主要是事件方面的应用. JavaScript并不能直接对Web对象进行操作,而是要通过浏览器提供的Documen

你必须知道的Javascript知识点之&quot;单线程事件驱动&quot;的使用

复制代码 代码如下: var intervalBody = function(){     console.log('interval'); } var startInterval = function(){     setInterval(intervalBody,1000); } var timeoutBody = function(){     console.log('timeout'); } var startTimeout = function(){     setTimeout(t

浅谈javascript基础之客户端事件驱动

我们知道,面向对象发展起来后,"一夜之间",几乎所有的语言都能基于对象了,JavaScript也是基于对象的语言.用户在浏览器上的行为称作"事件",之后引发的一系列动作,比如弹窗啦,改变浏览器大小啦,验证啦,balabala,都叫做"事件驱动".当然,这次我主要介绍几个常常发生的事件. ps:对于js脚本的支持以浏览器而定!!!有的低版本的浏览器可能不支持!!! 1.单击事件(onClick) 啥叫单击事件呢?当用户单击鼠标按钮是,就会产生单击事

Node.js中的事件驱动编程详解

在传统程编程模里,I/O操作就像一个普通的本地函数调用:在函数执行完之前程序被堵塞,无法继续运行.堵塞I/O起源于早先的时间片模型,这种模型下每个进程就像一个独立的人,目的是将每个人区分开,而且每个人在同一时刻通常只能做一件事,必须等待前面的事做完才能决定下一件事做什么.但是这种在计算机网络和Internet上被广泛使用的"一个用户,一个进程"的模型伸缩性很差.管理多个进程时,会耗费很多内存,上下文切换也会占用大量资源,这些对操作系统是个很大的负担,而且随着进程数的递增,会导致系统性能

理解 Node.js 事件驱动机制的原理

学习 Node.js 一定要理解的内容之一,文中主要涉及到了 EventEmitter 的使用和一些异步情况的处理,比较偏基础,值得一读. 大多数 Node.js 对象都依赖了 EventEmitter 模块来监听和响应事件,比如我们常用的 HTTP requests, responses, 以及 streams. const EventEmitter = require('events'); 事件驱动机制的最简单形式,是在 Node.js 中十分流行的回调函数,例如 fs.readFile.

Node.js事件驱动

Node.js事件驱动实现概览 虽然在ECMAScript的标准里并没有(也没有必要)明确规定"事件",但是在浏览器中,事件作为一个极为重要的机制,给予JavaScript响应用户操作与DOM变化的能力:在Node.js中,异步事件驱动模型则是其高并发能力的基础. 学习JavaScript也需要了解它的运行平台,为了更好的理解JavaScript的事件模型,我打算从Node及浏览器引擎源码入手,分析其底层实现,并将我的分析整理为一系列博文:一方面作为笔记,另一方面也希望能与大家交流,分

详解Javascript事件驱动编程

一.基本概述     JS是采用事件驱动的机制来响应用户操作的,也就是说当用户对某个html元素进行操作的时候,会产生一个时间,该时间会驱动某些函数来处理. PS:这种方式和Java GUI中的事件监听机制很像,都是需要注册监听,然后再处理监听,只不过实现的方式不同而已. 二.事件驱动原理 事件源:产生事件的地方(html元素) 事件:点击/鼠标操作/键盘操作等等 事件对象:当某个事件发生时,可能会产生一个事件对象,该时间对象会封装好该时间的信息,传递给事件处理程序 事件处理程序:响应用户事件的

详解JavaScript异步编程中jQuery的promise对象的作用

Promise, 中文可以理解为愿望,代表单个操作完成的最终结果.一个Promise拥有三种状态:分别是unfulfilled(未满足的).fulfilled(满足的).failed(失败的),fulfilled状态和failed状态都可以被监听.一个愿望可以从未满足状态变为满足或者失败状态,一旦一个愿望处于满足或者失败状态,其状态将不可再变化.这种"不可改变"的特性对于一个Promise来说非常的重要,它可以避免Promise的状态监听器修改一个Promise的状态导致别的监听器的行

JavaScript实现AOP详解(面向切面编程,装饰者模式)

什么是AOP? AOP(面向切面编程)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,这些跟业务逻辑无关的功能通常包括日志统计.安全控制.异常处理等.把这些功能抽离出来之后, 再通过"动态织入"的方式掺入业务逻辑模块中. AOP能给我们带来什么好处? AOP的好处首先是可以保持业务逻辑模块的纯净和高内聚性,其次是可以很方便地复用日志统计等功能模块. JavaScript实现AOP的思路? 通常,在 JavaScript 中实现 AOP,都是指把一个函数"动态织入&qu

详解Javascript中prototype属性(推荐)

在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不存在类(Class)的概念的,javascript中不是基于'类的',而是通过构造函数(constructor)和原型链(prototype chains)实现的.但是在ES6中提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板.通过class关键字,可以定义类.基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能

详解JavaScript中的Object.is()与&quot;===&quot;运算符总结

三重相等运算符 === 严格检查2个值是否相同: 1 === 1; // => true 1 === '1'; // => false 1 === true; // => false 但是,ES2015规范引入了 Object.is(),其行为与严格的相等运算符几乎相同: Object.is(1, 1); // => true Object.is(1, '1'); // => false Object.is(1, true); // => false 主要问题是:什么时

详解JavaScript 高阶函数

高阶函数简介 高阶函数 的英文名叫 Higher-Order Function ,是 函数式编程 中的一种.他的表现形式往往是通过把函数作为参数传入另一个函数,或者将函数作为另一个函数的返回值返回.在实际开发业务中, 高阶函数往往可以抽象我们的代码 ,将我们的命令式编程转换为复用性更高级的函数式编程,从而 提升我们的代码质量 . 下面拿3个面试中常问的高阶函数举例子,希望看完以后能够提升大家对JS的理解,提高我们的代码质量. chat is cheap,show you my code~ Arr

详解JavaScript 的执行机制

一.关于javascript javascript是一门单线程语言,在最新的HTML5中提出了Web Worker,但javascript是单线程这一核心仍未改变. 为什么js是单线程的语言?因为最初的js是用来在浏览器验证表单操纵DOM元素的.如果js是多线程的话,两个线程同时对一个DOM进行了相互冲突的操作,那么浏览器的解析是无法执行的. Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行.在主线程运行的同

详解JavaScript 事件流

事件 HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件.页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件.想要知道这些事件是在什么时候进行调用的,就需要了解一下"事件流"的概念. 事件流 事件流描述的就是从页面中接收事件的顺序.而早期的IE和Netscape提出了完全相反的事件流概念,IE事件流是事件冒泡,而Netscape的事件流就是事件捕获. 事件流类别 事件冒泡 即从下至上,从目标触发的元素逐级向上传播,直到win

详解JavaScript基于面向对象之创建对象(2)

接着上文<详解JavaScript基于面向对象之创建对象(1)>继续学习. 4.原型方式        我们创建的每个函数都有一个通过prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法.逻辑上可以这么理解:prototypt通过条用构造函数而创建的那个对象的原型对象.使用原型的好处就是可以让所有对象实例共享它所包含的属性和方法.也就是说,不必在构造函数中定义对象信息,而是直接将这些信息添加到原型中.        原型方式利用了对象的pr

详解JavaScript基于面向对象之继承实例

javascript面向对象继承的简单实例: 作为一门面向对象的语言,继承自然是它的一大特性,尽管javascript的面向对象的实现机制和和c#和java这样典型的面向对象不同,但是继承的基本特点还是具有的,简单的说就是获得父级的方法和属性,下面是一段简单的实例,大家有兴趣可以分析一下: window.onload = function(){ function parent(age,name){ this.age = age; this.name = name; } parent.protot