简体   繁体   English

事件驱动的编程-node.js,Java

[英]Event-driven programming - node.js, Java

I am coming from Java but have been doing some Node.js lately, and have been looking at the EventEmitter module in Node. 我来自Java,但是最近一直在做一些Node.js,并且一直在研究Node中的EventEmitter模块。

What I don't understand is the fundamental difference between Event-driven programming and 'regular' programming. 我不了解事件驱动的编程和“常规”编程之间的根本区别。

Here is some psuedo-code to demonstrate my idea of "event-driven" programming. 这是一些伪代码,以演示我对“事件驱动”编程的想法。

EventEmitter ee = new EventEmitter();
Function f = new SpecialFunction();

ee.on('grovel',f);

ee.emit('grovel'); //calls function 'f'

the only work the EventEmitter object seems to be doing is creating a hash relationship between the String representation of an event (in this case 'grovel') and a function to respond with. EventEmitter对象似乎唯一要做的工作是在事件的String表示形式(在本例中为“ grovel”)和一个响应函数之间创建哈希关系。 Seems like that's it, not much magic there. 似乎就是这样,那里没有太多魔术。

however, my question is - how does event-driven programming really work behind the scenes with low-level events like mouse-clicks and typing? 但是,我的问题是-事件驱动型编程如何真正在诸如鼠标单击和键入之类的低级事件发生后进行工作? In other words, how do we take a click and turn it into a string (like 'grovel') in our program? 换句话说,我们如何在程序中单击并转换为字符串(例如“ grovel”)?

Okay. 好的。 I will take a run at this. 我将对此进行尝试。

There are a couple of major reasons to use event emitters. 使用事件发射器有两个主要原因。

One of the main reasons is that the browser, which is where JavaScript was born, sometimes forces you to. 主要原因之一是JavaScript诞生的浏览器有时会迫使您这样做。 Whether you are wiring your events straight into your HTML, using jQuery or some other framework/library, or whatever, the underlying code is still basically the same (erm, basically...) 无论您是使用jQuery还是其他框架/库等将事件直接连接到HTML中,底层代码都基本相同(erm,基本上...)

So first, if you want to react to a keyboard or mouse event, like you mentioned, you could just hard bind directly to an event handler (callback) like this: 因此,首先,如果您想对键盘或鼠标事件做出反应(如前所述),则可以将硬绑定直接绑定到事件处理程序(回调),如下所示:

<div onclick="myFunc(this)">Click me</div>

...or you could do the exact same thing in JS by DOM reference: ...或者您可以通过DOM引用在JS中做完全相同的事情:

document.getElementById('my_element').onclick = function (evt) {
    alert('You clicked me');
};

This used to be the primary way we wired up click handlers. 这曾经是我们连接点击处理程序的主要方式。 One lethal drawback to this pattern is that you can only attach one callback to each DOM event. 这种模式的致命缺陷在于,您只能将一个回调附加到每个DOM事件。 If you wanted to have a second callback that reacted to the same event, you would either need to combine write it into the existing click handler or build a delegate function to handle the job of calling the two functions. 如果要让第二个回调对同一事件做出反应,则需要将其组合到现有的单击处理程序中,或者需要构建一个委托函数来处理调用这两个函数的工作。 Plus, your event emitter ends up being tightly coupled to the event listener, and that is generally a bad thing. 另外,事件发射器最终与事件侦听器紧密耦合,这通常是一件坏事。

As applications became more complex, it makes more sense to use event listeners, instead. 随着应用程序变得越来越复杂,使用事件侦听器变得更加有意义。 Browser vendors (eventually) settled on a single way to do this: 浏览器供应商(最终)选择了一种单一的方法来做到这一点:

// Build the handler
var myHandler = function (evt) {
    alert('You clicked me too');
    window.myHandlerRef = this; // Watch out! See below.
};

// Bind the handler to the DOM event
document.getElementById('my_element').addEventListener('click', myHandler);

The advantage to this pattern is that you can attach multiple handlers to a single DOM event, or call one single event handler from several different DOM events. 这种模式的优势在于,您可以将多个处理程序附加到一个DOM事件,或者从几个不同的DOM事件中调用一个事件处理程序。 The disadvantage is that you have to be careful not to leak: depending on how you write them, event-handling closures (like myHandler above) can continue to exist after the DOM element to which they were attached have been destroyed and GCed. 缺点是您必须注意不要泄漏:根据事件的编写方式,事件处理闭包(如上面的myHandler )在销毁它们并附加了GC的DOM元素后可以继续存在。 This means it is good practice to always do a removeEventListener('click', myHandler) . 这意味着最好始终执行removeEventListener('click', myHandler) (Some libraries have an off() method that does the same thing). (某些库具有执行相同操作的off()方法)。

This pattern works well for keyboard events as well: 此模式也适用于键盘事件:

var giveUserAHeadache = function (evt) {
    alert('Annoying, isn\'t it?');
};

document.addEventListener('keypress', giveUserAHeadache);

Okay. 好的。 So that is how you usually handle native browser events. 因此,这通常就是处理本机浏览器事件的方式。 But developers also like to use this pattern of event delegation in their own code. 但是开发人员也喜欢在自己的代码中使用这种事件委托模式。 The reason you would want to do this is so you can decouple your code as much as possible. 您想要这样做的原因是,您可以尽可能地使代码解耦。

For example, in a UI, you could have an event emitted every time the user's browser goes offline (you might watch navigator.onLine for example). 例如,在用户界面中,每次用户的浏览器离线时,您可能会navigator.onLine一个事件(例如,您可能会观看navigator.onLine )。 Maybe you could have a green/red lamp on your page header to show the online state, and maybe you could disable all submit buttons when offline, and maybe also show a warning message in the page footer. 也许页面标题上的绿色/红色指示灯会显示在线状态,并且可能在脱机时禁用所有提交按钮,也可能在页面页脚中显示警告消息。 With event listeners/emitters, you could write all of these as completely decoupled modules and they still can work in lock-step. 使用事件侦听器/发射器,您可以将所有这些编写为完全解耦的模块,并且它们仍可以按步进行工作。 And if you need to refactor your UI, you can remove one component (the lamp, for example), replace it with something else without worrying about screwing up the logic in some other module. 而且,如果您需要重构UI,则可以删除一个组件(例如,灯),将其替换为其他组件,而不必担心会弄乱其他模块中的逻辑。

As another example, in a Node app you might want your database code to emit an error condition to a particular controller and also log the error -- and maybe send out an email. 再举一个例子,在Node应用程序中,您可能希望您的数据库代码向特定的控制器发出错误情况并记录错误-并发送电子邮件。 You can see how these sorts of things might get added iteratively. 您可以看到这些事情是如何迭代添加的。 With event listeners, this sort of thing is easy to do. 使用事件侦听器,这种事情很容易实现。

You can either write your own, or you can use whatever pattern is available in your particular environment. 您可以编写自己的代码,也可以使用特定环境中可用的任何模式。 jQuery, Angular, Ember and Node all have their particular methods, but you are free to also build your own -- which is what I would encourage you to try. jQuery,Angular,Ember和Node都有其特定的方法,但是您可以自由地构建自己的方法,这是我鼓励您尝试的方法。

These are all variations of the same basic idea and there is a LOT of blur over the exact definition or most correct implementation (in fact, some might question if these are different at all). 这些都是同一基本思想的变体,确切的定义或最正确的实现存在很多模糊(实际上,有些人可能会质疑这些是否根本不同)。 But here are the main culprits: 但是,这是主要的罪魁祸首:

  1. Observer 观察
  2. Pub-Sub 发布-订阅
  3. Mediator 中间人

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM