Events 为什么在函数调用上使用事件侦听器?

Events 为什么在函数调用上使用事件侦听器?,events,event-handling,event-listener,Events,Event Handling,Event Listener,我最近一直在研究事件听众,我想我终于把他们弄下来了。基本上,它们是在另一个对象的方法上调用的函数。我的问题是,为什么在调用函数时创建一个事件侦听器就可以正常工作呢 例如,我想调用player.display\u health(),当它被激发时,应该激发并存储方法player.get\u health(),以便display\u health()可以访问它。为什么我应该使用事件侦听器而不是简单地调用函数?即使display_health()位于另一个对象中,这对我来说仍然不是问题 如果你有另一个更

我最近一直在研究事件听众,我想我终于把他们弄下来了。基本上,它们是在另一个对象的方法上调用的函数。我的问题是,为什么在调用函数时创建一个事件侦听器就可以正常工作呢

例如,我想调用player.display\u health(),当它被激发时,应该激发并存储方法player.get\u health(),以便display\u health()可以访问它。为什么我应该使用事件侦听器而不是简单地调用函数?即使display_health()位于另一个对象中,这对我来说仍然不是问题

如果你有另一个更适合使用的例子,请让我知道。也许某些特定的语言并没有从中受益那么多?(Javascript、PHP、ASP?)

我的问题是,为什么在调用函数时创建一个事件侦听器就可以正常工作呢

如果您不知道要调用什么函数呢

举个经典的例子,一个用户可以点击的按钮。无论谁编写库,都不知道单击按钮时要调用什么函数。如果每个按钮都只能在单击时调用同一个函数,那么这也是非常禁止的


因此,您可以将事件处理程序附加到事件。然后,当事件被触发时,按钮可以执行它需要执行的操作,而不必在编译时知道它应该调用什么函数。

您可能并不总是能够控制执行调用的代码。或者,即使是这样,也不想在代码中引入依赖项。在这种情况下,最好让代码触发事件,并允许您控制的代码或应该具有依赖性的代码侦听事件并相应地执行操作

例如,您可能正在创建一个供其他人使用的库。他们没有源代码,或者在某种程度上不能/不应该修改(或者不应该修改)。您的文档说明特定事件是在特定情况下引发的。然后,他们可以反过来对这些事件作出反应

或者,您的企业中可能有一些域库。您确实可以控制它们,并且可以修改它们,但是在架构上,它们通常被认为是工作的,因为它们当前是编码的,不应该被更改。(不希望招致一轮QA来重新验证更新的代码,代码属于另一个部门,他们不希望您更改它,等等),并且您希望该代码能够在不同的环境/环境中执行不同的操作。如果该代码在相关的地方引发和事件,您可以将代码挂接到其中(和/或相应地交换),而不必弄乱该代码


仅举几个简单的例子,我相信其他人会有更多。

简而言之,您可以在不使用事件侦听器的情况下编写代码,但使用事件侦听器可以帮助其他人使用与库相同的代码

即使有了上面的详细答案,我仍然无法理解使用控制器/函数或事件侦听器之间的实际区别

在所有这些答案中被忽略的一点是,当您不想将代码紧密结合时,事件和事件侦听器的使用非常方便。每个函数、类等都应具有单一的用途

因此,假设您遇到来自外部人员的API请求。在我的例子中,理解这个概念的确切问题是当我从Stripe Webhook接收API调用时

Stripe Webhooks的目的是:假设客户在您的网站上花费10000美元。您的标准过程是进行身份验证和捕获。更新数据库以反映其新成员身份状态。在一个完美的世界里,在我们公司的情况下,999/1000次,这一切都是完美的。要么他们的卡当场被拒绝,要么付款通过。在这两种情况下,我们都会向他们发送电子邮件,让他们知道

但是,当用户付费并返回一个卡故障错误(可能是许多不同的事情)时,1/1000的时间又如何呢?在我们的情况下,我们给他们发电子邮件,告诉他们账单失败了。我们遇到的问题是,一些银行正在调查大额费用,这是一个错误,但几分钟后,银行批准了这些费用,并捕获了付款

那怎么办呢?输入stripewebhooks。如果出现类似情况,条带Webhook将命中API端点。事实上,Stripe Webhooks可以在每次付款未立即授权、捕获或客户要求退款的情况下攻击您的API

这就是事件侦听器派上用场的地方。Stripe在带有客户信息以及Webhook类型的帖子上拍摄。我们现在将处理这个问题,更新数据库,并向他们发送一封成功的电子邮件

但为什么不使用标准路线和控制器呢? 我们不使用标准路由和控制器的原因是,我们需要修改已经定义的函数、类等,或者创建一系列耦合在一起的新类,例如->接收的条带API调用、更新DB、发送电子邮件。我们使用一个事件监听器来首先接受API调用,然后点击这些类、函数等等,而不是将它们紧密地耦合在一起,从而使一切都不耦合

我看了所有地方,我认为Laravel的文档最好地解释了这一点。当给出一个具体的例子时,我终于明白了事件侦听器的目的是什么:

事件是解耦应用程序各个方面的好方法,因为单个事件可以有多个互不依赖的侦听器。例如,您可能希望在每次发货订单时向用户发送延迟通知。不必将订单处理代码与松弛通知代码耦合,您可以
var events = require('events');
var Person = function(pname) {
    var name = pname;
};


var james = new Person('james');
var mary = new Person('mary');
var loudmouth = new Person('blabberer');

loudmouth.mouth = new events.EventEmitter();

//jame's observer.
james.read_lips = function(msg){
    console.log("james found out: " + msg);
};

//james adds his event to the emitter's event listener.
james.enter_elevator = function(){
    console.log('james is in the elevator');
    //NOTE: james adds HIMSELF as a listener for the events that may
    //transpire while he is in the elevator.
    loudmouth.mouth.on('elevator gossip', james.read_lips)
};

//james removes his event from the emitter when he leaves the elevator.
james.leave_elevator = function(){
    // read lips is how james responds to the event.
    loudmouth.mouth.removeListener('elevator gossip', james.read_lips);
    console.log('james has left the elevator');
};

//mary's observer
mary.overhear = function(msg){
    console.log("mary heard: " + msg);
};

//mary adds her observer event to the emitter's event listeners
mary.enter_elevator = function(){
    // overhear is how mary responds to the event.
    console.log('mary is in the elevator');
    //NOTE: now mary adds HERSELF to the listeners in the elevator and 
    //she observes using a different method than james which suits her.
    loudmouth.mouth.on('elevator gossip', mary.overhear);
};

loudmouth.speaks = function(what_is_said){
    console.log('loudmouth: ' + what_is_said);
    this.mouth.emit('elevator gossip', what_is_said);
};

james.enter_elevator();
mary.enter_elevator();
loudmouth.speaks('boss is having an affair');
james.leave_elevator();
loudmouth.speaks('just kidding');
console.log('james did not hear the last line because he was not listening anymore =)');