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



我来自Java,但最近一直在做一些Node.js并且一直在查看Node中的EventEmitter模块。

我不明白的是事件驱动编程和"常规"编程之间的根本区别。

这里有一些伪代码来展示我对"事件驱动"编程的想法。

EventEmitter ee = new EventEmitter();
Function f = new SpecialFunction();
ee.on('grovel',f);
ee.emit('grovel'); //calls function 'f'

EventEmitter 对象似乎正在做的唯一工作是在事件的 String 表示形式(在本例中为"grovel"(和要响应的函数之间创建哈希关系。好像就是这样,那里没有多少魔法。

但是,我的问题是 - 事件驱动编程如何在幕后真正处理鼠标单击和键入等低级事件?换句话说,我们如何在我们的程序中单击并将其转换为字符串(如"grovel"(?

好的。我会跑一试。

使用事件发射器有几个主要原因。

其中一个主要原因是浏览器,这是JavaScript诞生的地方,有时会强迫你这样做。无论你是将事件直接连接到HTML中,使用jQuery或其他框架/库,还是其他什么,底层代码仍然基本相同(呃,基本上......

因此,首先,如果要对键盘或鼠标事件做出反应,就像您提到的那样,您可以直接硬绑定到事件处理程序(回调(,如下所示:

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

。或者你可以通过 DOM 引用在 JS 中做完全相同的事情:

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

这曾经是我们连接点击处理程序的主要方式。此模式的一个致命缺点是,您只能将一个回调附加到每个 DOM 事件。如果要对同一事件做出反应的第二个回调,则需要将其合并到现有的单击处理程序中,或者构建一个委托函数来处理调用这两个函数的作业。另外,您的事件发射器最终会与事件侦听器紧密耦合,这通常是一件坏事。

随着应用程序变得越来越复杂,改用事件侦听器更有意义。浏览器供应商(最终(决定采用一种方法来做到这一点:

// 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);

此模式的优点是可以将多个处理程序附加到单个 DOM 事件,或者从多个不同的 DOM 事件调用单个事件处理程序。缺点是你必须小心不要泄漏:根据你如何编写它们,事件处理闭包(如上面的myHandler(可以在它们所附加到的 DOM 元素被销毁和 GCed 后继续存在。这意味着最好总是做一个removeEventListener('click', myHandler)。(某些库具有执行相同操作的off()方法(。

此模式也适用于键盘事件:

var giveUserAHeadache = function (evt) {
    alert('Annoying, isn't it?');
};
document.addEventListener('keypress', giveUserAHeadache);

好。这就是您通常处理本机浏览器事件的方式。但开发人员也喜欢在自己的代码中使用这种事件委托模式。您希望这样做的原因是,您可以尽可能分离代码。

例如,在 UI 中,每次用户的浏览器脱机时,您都可以发出一个事件(例如,您可以观看navigator.onLine(。也许您可以在页眉上有一个绿色/红色灯来显示在线状态,也许您可以在离线时禁用所有提交按钮,并且还可以在页面页脚中显示警告消息。使用事件侦听器/发射器,您可以将所有这些编写为完全解耦的模块,并且它们仍然可以同步工作。如果您需要重构UI,则可以删除一个组件(例如灯(,将其替换为其他组件,而不必担心搞砸其他模块中的逻辑。

再举一个例子,在 Node 应用程序中,您可能希望数据库代码向特定控制器发出错误条件并记录错误 - 并可能发送电子邮件。您可以看到如何迭代添加这些内容。使用事件侦听器,这种事情很容易做到。

您可以编写自己的模式,也可以使用特定环境中可用的任何模式。 jQuery,Angular,Ember和Node都有其特定的方法,但您也可以自由构建自己的方法 - 这是我鼓励您尝试的。

这些都是同一基本思想的变体,并且在确切的定义或最正确的实现上存在很多模糊(事实上,有些人可能会质疑这些是否不同(。但这是罪魁祸首:

  1. 观察者
  2. 发布-订阅
  3. 调解人

最新更新