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/

如何正确使用Node.js中的事件相关推荐

  1. 在Node.js中使用事件,监听器,定时器和回调

    Node.js通过其强大的事件驱动模型提供了可扩展性和性能,本篇文章的重点是理解该模型,以及它是如何不同于大部分Web服务器采用的传统线程模型的.了解事件模型至关重要,因为它可能迫使你改变设计应用程序 ...

  2. 【nodejs原理源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick

    [摘要] 官网博文翻译,nodejs中的定时器 示例代码托管在:http://www.github.com/dashnowords/blogs 原文地址:https://nodejs.org/en/d ...

  3. 5.node.js中的事件循环

    先举一个简单的例子 const bar = () => console.log('bar')const baz = () => console.log('baz')const foo = ...

  4. Day 27: Restify —— 在Node.js中构建正确的REST Web服务

    今天决定学一个叫做restify的Node.js模块.restify模块使得在Node.js中写正确的REST API变得容易了很多,而且它还提供了即装即用的支持,如版本控制.错误处理.CORS和内容 ...

  5. 在node.js中一次读取一行文件?

    本文翻译自:Read a file one line at a time in node.js? I am trying to read a large file one line at a time ...

  6. react性能优化方案_React灵敏且性能卓越的Spray + Akka解决方案,以“在Java和Node.js中发挥并发性和性能”...

    react性能优化方案 在我以前的文章中,我研究了一个虚拟的交易引擎,并将基于Java的阻止解决方案与基于Node.js的非阻止解决方案进行了比较. 在文章的结尾,我写道: 我怀疑随着Node.js的 ...

  7. 反应灵敏且性能卓越的Spray + Akka解决方案,以“在Java和Node.js中发挥并发性和性能”...

    在我以前的文章中,我研究了一个虚拟的交易引擎,并将基于Java的阻止解决方案与基于Node.js的非阻止解决方案进行了比较. 在文章的结尾,我写道: 我怀疑在Node.js近期取得成功之后,越来越多的 ...

  8. 如何在Node.js中处理POST数据?

    如何提取Node.js中 HTTP POST方法发送的表单数据( form[method="post"] )和文件上传? 我已经阅读了文档,谷歌搜索并没有发现任何东西. funct ...

  9. [转]JavaScript/Node.JS 中的 Promises

    JavaScript Promises 初体验 Promise 是什么? Promise 对象用来进行延迟(deferred) 和 异步(asynchronous) 计算. 一个 Promise 处于 ...

最新文章

  1. chrome java插件_selenium启动Chrome配置参数问题
  2. 25 navigator对象
  3. CSS:超出部分省略号
  4. JSP+Servlet + JDBC 实现简单的登录验证模块
  5. 2021-03-16 汽车二自由度操纵稳定性 Matlab simulink
  6. linux ssh互免密配置
  7. [MATLAB粒子模拟笔记]归一化输入系数
  8. Linux把文件移动到容器外,Docker容器与主机之间拷贝文件的方法
  9. 选择什么技术,才能不被淘汰?180 所高校在增设这个专业!
  10. cj20n sap 报错未知列的名称_SAP,PS模块配置和操作手册
  11. Android学习笔记一:Android基本组件和Activity生命周期
  12. Linux命令之iconv命令
  13. 我的世界启动时要Java_我的世界启动时Java出现日志怎么办
  14. 国内最强Web3D软件WebMax正式版发布
  15. 【C语言】OJ题:printf函数的返回值
  16. idea单测覆盖率不显示的问题
  17. 设计模式04——Factory Method模式
  18. 裁桨研纳铰撼蕉吞字吞汗屠闯汗芳
  19. jquery+ajx post/get 实例
  20. 文件服务器文件删除记录查询,Windows server2008r2共享文件操作记录、查询服务器日志方法...

热门文章

  1. 大牛深入讲解!高并发你真的理解透彻了吗
  2. C# 篇基础知识10——多线程
  3. 【转】WPF自定义控件与样式(3)-TextBox RichTextBox PasswordBox样式、水印、Label标签、功能扩展...
  4. bzoj 4300 绝世好题 —— 思路
  5. Android商城开发系列(二)——App启动欢迎页面制作
  6. Cppunit 源码 SynchronizedObject
  7. session 学习
  8. Linux 下 新增Oracle10g 实例
  9. mysql全文索引中文问题的解决(转)
  10. [导入]关于OllyDbg 2.0的消息..