如何正确使用Node.js中的事件

by Usama Ashraf

通过Usama Ashraf

如何正确使用Node.js中的事件 (How to use events in Node.js the right way)

Before event-driven programming became popular, the standard way to communicate between different parts of an application was pretty straightforward: a component that wanted to send out a message to another one explicitly invoked a method on that component. But event-driven code is written to react rather than be called.

在事件驱动的编程流行之前,在应用程序的不同部分之间进行通信的标准方法非常简单:一个组件希望向另一个发出消息,而该组件显式调用了该组件上的方法。 但是事件驱动的代码是为了响应而不是被调用而编写的。

比赛的好处 (The Benefits Of Eventing)

This approach causes our components to be much more decoupled. As we continue to write an application, we identify events along the way. We fire them at the right time and attach one or more event listeners to each one. Extending functionality becomes much easier. We can add on more listeners to a particular event. We are not tampering with the existing listeners or the part of the application where the event was fired from. What we’re talking about is the Observer pattern.

这种方法使我们的组件更加分离 。 在继续编写应用程序的过程中,我们一路确定事件。 我们在适当的时间解雇它们,并将一个或多个事件侦听器附加到每个侦听器扩展功能变得容易得多。 我们可以为特定事件添加更多的侦听器。 我们不会篡改现有的侦听器或触发事件的应用程序部分。 我们正在谈论的是观察者模式。

设计事件驱动的体系结构 (Designing An Event-Driven Architecture)

Identifying events is pretty important. We don’t want to end up having to remove/replace existing events from the system. This might force us to delete/modify any number of listeners that were attached to the event. The general principle I use is to consider firing an event only when a unit of business logic finishes execution.

识别事件非常重要。 我们不想最终不得不从系统中删除/替换现有事件。 这可能迫使我们删除/修改附加到该事件的任意数量的侦听器。 我使用的一般原则是仅在业务逻辑单元完成执行时才考虑触发事件。

So say you want to send out a bunch of different emails after a user’s registration. Now, the registration process itself might involve many complicated steps, and queries. But from a business point of view, it is one step. And each of the emails to be sent out are individual steps as well. So it would make sense to fire an event as soon as registration finishes. We have multiple listeners attached to it, each responsible for sending out one type of email.

假设您要在用户注册后发送大量不同的电子邮件。 现在,注册过程本身可能涉及许多复杂的步骤和查询。 但是从业务角度来看,这只是一步。 而且,要发送的每封电子邮件都是单独的步骤。 因此,在注册完成后立即触发事件是很有意义的。 我们具有多个侦听器,每个侦听器负责发送一种电子邮件。

Node’s asynchronous, event-driven architecture has certain kinds of objects called “emitters.” They emit named events which cause functions called “listeners” to be invoked. All objects that emit events are instances of the EventEmitter class. Using it, we can create our own events:

Node的异步事件驱动架构具有某些称为“发射器”的对象。 它们发出命名事件,这些事件导致称为“侦听器”的函数被调用。 所有发出事件的对象都是EventEmitter类的实例。 使用它,我们可以创建自己的事件:

一个例子 (An Example)

Let’s use the built-in events module (which I encourage you to check out in detail) to gain access to EventEmitter.

让我们使用内置的事件模块(我建议您详细检查该模块)来访问EventEmitter

This is the part of the application where our server receives an HTTP request, saves a new user and emits an event:

这是服务器接收HTTP请求,保存新用户并发出事件的应用程序的一部分:

And a separate module where we attach a listener:

还有一个单独的模块,我们在其中附加了一个侦听器:

It’s a good practice to separate policy from implementation. In this case policy means which listeners are subscribed to which events. Implementation means the listeners themselves.

将政策与实施分开是一个好习惯 在这种情况下,策略意味着哪些侦听器订阅了哪些事件。 实现是指侦听器本身。

This separation allows for the listener to become re-usable too. It can be attached to other events that send out the same message (a user object). It’s also important to mention that when multiple listeners are attached to a single event, they will be executed synchronously and in the order that they were attached. Hence someOtherListener will run after sendEmailOnRegistration finishes execution.

这种分离也使侦听器也可以重用。 它可以附加到发出相同消息的其他事件(用户对象)。 同样重要的是要提到, 当多个侦听器附加到一个事件时,它们将按照附加的顺序同步执行 。 因此, someOtherListener将在sendEmailOnRegistration完成执行之后运行。

However, if you want your listeners to run asynchronously you can simply wrap their implementations with setImmediate like this:

但是,如果您希望监听器异步运行,则可以使用setImmediate包装它们的实现,如下所示:

保持听众干净 (Keep Your Listeners Clean)

Stick to the Single Responsibility Principle when writing listeners. One listener should do one thing only and do it well. Avoid, for instance, writing too many conditionals within a listener that decide what to do depending on the data (message) that was transmitted by the event. It would be much more appropriate to use different events in that case:

编写侦听器时,请遵循“单一责任原则”。 一个听众应该只做一件事,并且做好。 例如,避免在侦听器中编写太多条件,以根据事件传输的数据(消息)来决定要做什么。 在这种情况下,使用不同的事件会更合适:

在必要时明确分离侦听器 (Detaching Listeners Explicitly When Necessary)

In the previous example, our listeners were totally independent functions. But in cases where a listener is associated with an object (it’s a method), it has to be manually detached from the events it had subscribed to. Otherwise, the object will never be garbage-collected since a part of the object (the listener) will continue to be referenced by an external object (the emitter). Thus the possibility of a memory leak.

在前面的示例中,我们的侦听器是完全独立的功能。 但是,如果侦听器与对象(这是一种方法)相关联,则必须将其与已订阅的事件手动分离。 否则,该对象将永远不会被垃圾回收,因为该对象的一部分(侦听器)将继续被外部对象(发射器)引用。 因此存在内存泄漏的可能性。

For example, if we’re building a chat application and we want the responsibility for showing a notification when a new message arrives in a chat room that a user has connected to should lie within that user object itself, we might do this:

例如,如果我们正在构建一个聊天应用程序,并且我们希望当用户连接到的新消息到达聊天室时,负责显示通知的责任应该位于该用户对象本身内,我们可以这样做:

When the user closes his/her tab or loses their internet connection for a while, naturally, we might want to fire a callback on the server-side that notifies the other users that one of them just went offline. At this point, of course, it doesn’t make any sense for displayNewMessageNotification to be invoked for the offline user. It will continue to be called on new messages unless we remove it explicitly. If we don’t, aside from the unnecessary call, the user object will also stay in memory indefinitely. So be sure to call disconnectFromChatroom in your server-side callback that executes whenever a user goes offline.

当用户关闭其选项卡或暂时失去其互联网连接时,自然地,我们可能希望在服务器端触发回调,以通知其他用户其中一个刚下线。 当然,在这一点上,为脱机用户调用displayNewMessageNotification没有任何意义。 除非我们明确删除它,否则它将继续在新消息上被调用。 如果我们不这样做,除了不必要的调用之外,用户对象还将无限期地保留在内存中。 因此,请确保在用户下线时执行的服务器端回调中调用disconnectFromChatroom

谨防 (Beware)

The loose coupling in event-driven architectures can also lead to increased complexity if we’re not careful. It can be difficult to keep track of dependencies in our system. Our application will become especially prone to this problem if we start emitting events from within listeners. This could possibly trigger chains of unexpected events.

如果我们不小心,事件驱动的体系结构中的松散耦合也会导致复杂性的增加。 跟踪我们系统中的依赖关系可能很困难。 如果我们开始从侦听器内部发出事件,我们的应用程序将特别容易出现此问题。 这可能会触发一系列意外事件。

翻译自: https://www.freecodecamp.org/news/using-events-in-node-js-the-right-way-fc50c060f23b/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/392897.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

你的成功有章可循

读书笔记 作者 海军 海天装饰董事长 自我修炼是基础。通过自我学习,在预定目标的指引下,将获取的知识转化为个人能力,形成自我规律,不断循环,实现成功。 寻找和掌握规律,并熟练运用于实践,是成功…

98k用计算机图片,98K (HandClap)_谱友园地_中国曲谱网

《98K》文本歌词98K之歌-HandClap-抖音 制谱:孙世彦这首《HandClap》是Fitz&TheTantrums乐队演唱的一首歌曲,同时也是绝地求生中嚣张BGM,是一首吃鸡战歌!这首歌谱曲者和填词者都是三个人:JeremyRuzumna&#xff0c…

qt之旅-1纯手写Qt界面

通过手写qt代码来认识qt程序的构成,以及特性。设计一个查找对话框。以下是设计过程1 新建一个empty qt project2 配置pro文件HEADERS \Find.h QT widgetsSOURCES \Find.cpp \main.cpp3 编写对话框的类代码例如以下://Find.h #ifndef FIND_H #define F…

【随笔】写在2014年的第一天

想想好像就在不久前还和大家异常兴奋地讨论着世界末日的事,结果一晃也是一年前的事了。大四这一年,或者说整个2013年都是场摇摆不定的戏剧,去过的地方比前三年加起来还多的多,有时候也会恍惚地不知道自己现在在哪。简单记几笔&…

设计冲刺下载_如何运行成功的设计冲刺

设计冲刺下载by George Krasadakis通过乔治克拉萨达基斯(George Krasadakis) Design Sprints can generate remarkable output for your company — such as a backlog of impactful ideas, functional prototypes, learning and key insights from customers along with real…

leetcode 18. 四数之和(双指针)

给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a b c d 的值与 target 相等?找出所有满足条件且不重复的四元组。 注意: 答案中不可以包含重…

WPF:从WPF Diagram Designer Part 4学习分组、对齐、排序、序列化和常用功能

在前面三篇文章中我们介绍了如何给图形设计器增加移动、选择、改变大小及面板、缩略图、框线选择和工具箱和连接等功能,本篇是这个图形设计器系列的最后一篇,将和大家一起来学习一下如何给图形设计器增加分组、对齐、排序、序列化等功能。 WPF Diagram D…

win7如何看计算机用户名和密码怎么办,win7系统电脑查看共享文件夹时不显示用户名和密码输入窗口的解决方法...

win7系统使用久了,好多网友反馈说win7系统电脑查看共享文件夹时不显示用户名和密码输入窗口的问题,非常不方便。有什么办法可以永久解决win7系统电脑查看共享文件夹时不显示用户名和密码输入窗口的问题,面对win7系统电脑查看共享文件夹时不显…

ASP.NET Core跨域设置

项目中经常会遇到跨域问题,解决方法: 在appsettings.json 文件中添加json项 {"Logging": {"LogLevel": {"Default": "Warning"}},"AllowedHosts": "*","AppCores": "https…

微信客户端<->腾讯微信服务器<->开发者服务器

出自 http://blog.csdn.net/hanjingjava/article/details/41653113 首先,通过Token验证,将公众号接入开发者服务器,这样客户端发给公众号的信息会被转发给开发者服务器; 第二,组装微信特定消息格式,返回给用…

idea提高调试超时_如何提高您的调试技能

idea提高调试超时by Nick Karnik尼克卡尼克(Nick Karnik) 如何提高您的调试技能 (How to Improve Your Debugging Skills) All of us write code that breaks at some point. That is part of the development process. When you run into an error, you may feel that you do…

leetcode 834. 树中距离之和(dp)

给定一个无向、连通的树。树中有 N 个标记为 0...N-1 的节点以及 N-1 条边 。第 i 条边连接节点 edges[i][0] 和 edges[i][1] 。返回一个表示节点 i 与其他所有节点距离之和的列表 ans。示例 1:输入: N 6, edges [[0,1],[0,2],[2,3],[2,4],[2,5]] 输出: [8,12,6,10,10,10] 解…

CSS设计指南(读书笔记 - 背景)

本文转自william_xu 51CTO博客,原文链接:http://blog.51cto.com/williamx/1140006,如需转载请自行联系原作者

在计算机网络中 带宽是什么,在计算机网络中,“带宽”用____表示。

答案查看答案解析:【解析题】计算机的发展经历了4个时代,各个时代划分的原则是根据()。【解析题】计算机网络的最主要的功能是______。【解析题】冯.诺依曼提出的计算机工作原理为____。【解析题】计算机的通用性使其可以求解不同的算术和逻辑问题,这主要…

如何在iOS上运行React Native应用

by Soujanya PS通过Soujanya PS 如何在iOS上运行React Native应用 (How to run a React Native app on iOS) I recently started to develop a React-Native app on iOS. This was my first foray into native app development. I was surprised by the ease and level of abs…

导出excel 后 页面按钮失效(页面假死)

在 page_load 里加上如下代码:string beforeSubmitJS "\nvar exportRequested false; \n"; beforeSubmitJS "var beforeFormSubmitFunction theForm.onsubmit;\n"; beforeSubmitJS "theForm.onsubmit function(){ \n"; …

Mysql分组查询group by语句详解

(1) group by的含义:将查询结果按照1个或多个字段进行分组,字段值相同的为一组(2) group by可用于单个字段分组,也可用于多个字段分组 select * from employee; --------------------------------------------- | num | d_id | name | age | sex | homea…

leetcode 75. 颜色分类(双指针)

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 注意: 不能使用代码…

火车头如何才能设置发布的时候,如果是有html代码就直接的转换掉,互联网上笑话抽取及排重---火车头采集器的使用和MD5算法的应用...

10011311341 吕涛、10011311356李红目的:通过熟悉使用火车头采集器,在网络上采取3万条笑话并进行排重,以此来熟悉web文本挖掘的一些知识。过程:本次学习,主要分成两个部分。第一部分是笑话文本的采集,第二部…

Tcp_wrapper

在Linux进程分为:独立进程和非独立进程非独立进程:是依赖于超级守护进程的进程, 且受Xinetd 管理,并在启动服务时 必须启动例子:#chkconfig –level 2345 telnetd on关与chkconfig 的命令:#chkconfig –lis…