Why use event listeners over function calls?

前端 未结 5 1607
盖世英雄少女心
盖世英雄少女心 2021-01-17 12:02

I\'ve been studying event listeners lately and I think I\'ve finally gotten them down. Basically, they are functions that are called on another object\'s method. My questi

相关标签:
5条回答
  • 2021-01-17 12:07

    You might not always be in control of the code that's doing the calling. Or even if you are, you don't want to introduce dependencies into that code. In cases like that, it's better for the code to fire an event and allow the code you do control, or the code that should have the dependency, to listen for the event and act accordingly.

    For example, perhaps you're creating a library that will be used by other people. They don't have the source code or in some way can't/shouldn't be able to modify it (or shouldn't have to). Your documentation states that specific events are raised under specific circumstances. They can then, in turn, respond to those events.

    Or perhaps you have some domain libraries in your enterprise. You do control them and can modify them, but architecturally they're generally considered to be working as they currently are coded and shouldn't be changed. (Don't want to incur a round of QA to re-validate the updated code, the code belongs to another department and they don't want you to change it, etc.) And you're in the position where you want that code to be able to do different things in different circumstances/environments. If that code raises and event where relevant, you can hook your code into it (and/or swap out accordingly) without having to mess with that code.

    Just a couple quick examples, I'm sure others have more.

    0 讨论(0)
  • 2021-01-17 12:18

    Even with the detailed answers above, I was still having trouble understanding what the actual difference was between using a controller / functions OR an event listener.

    One of the things that has been left out in all of these answers is that the use of Events and Event Listeners comes in handy when you do not want to couple your code so closely. Each function, class, etc, should have singleness of purpose.

    So say you are getting hit with an API request from an outsider. In my case, my exact problem understanding this concept was when I am receiving API calls from Stripe Webhooks.

    The purpose of Stripe Webhooks is: say a customer spends $10,000 on your website. Your standard procedure is to Auth and Capture. Update DB to reflect their new membership status. In a perfect world, and in our company's case, 999/1000 times, this goes perfectly. Either their card is declined on the spot, or the payment goes through. In both cases, we send them an email letting them know.

    But what about the 1/1000 time when the user pays and Stripe returns a Card Failure error (which can be a number of different things)? In our case, we email them and tell them the billing has failed. The problem we've encountered is that some BANKS are investigating large charges, which comes back as an Error, but then a few minutes later the bank authorizes the charges and the payment is captured.

    So what is there to do? Enter Stripe Webhooks. Stripe Webhooks will hit an API endpoint if something like this occurs. Actually, Stripe Webhooks can hit your API any and every time a payment isn't instantly Authed, Captured, or if the customer asks for a refund.

    This is where an Event Listener comes in handy. Stripe shoots over a POST with the customer info, as well as the Webhook type. We will now process that, update the database, and shoot them a success email.

    But why not just use a standard route and controller? The reason we don't just use a standard route and controller is because we would either need to modify the already defined functions, classes, etc, or create a new series of classes that are coupled together, such as -> Stripe API Calls Received, Update DB, Send Email. Instead of coupling these closely together, we use an Event Listener to first accept the API Call, then hit each of those Classes, Functions, etc., leaving everything uncoupled.

    I looked everywhere, and I think the Laravel documentation explains it best. I finally understood when given a concrete example, and what the purpose of an Event Listener is:

    Events serve as a great way to decouple various aspects of your application, since a single event can have multiple listeners that do not depend on each other. For example, you may wish to send a Slack notification to your user each time an order has shipped. Instead of coupling your order processing code to your Slack notification code, you can raise an OrderShipped event, which a listener can receive and transform into a Slack notification.

    https://laravel.com/docs/5.6/events

    0 讨论(0)
  • 2021-01-17 12:21

    I think the main reason for events vs function calls is that events are 'listened to' while calls are 'made'. So a function call is always made to another object whereas listeners 'choose' to listen for an event to be broadcast from your object. The observer pattern is a good study for this capability. Here is a brief node.js example which illustrates the concept:

    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 =)');
    

    so in this 'story' the actors choose to listen or when to not listen for events from a third party. I hope this helps.

    0 讨论(0)
  • 2021-01-17 12:25

    My question is, why create an event listener when calling the function will work just fine?

    What if you don't know what function you want to call?

    Take the classic example, a Button that the user can click on. Whoever writes the library has no idea what function you want called when the button is clicked. It would also be pretty prohibitive if every Button could only call the same function when it is clicked.

    So instead, you can attach an event handler to the event. Then when the event is triggered, the Button can do what it needs to, without having to know at compile-time exactly what function it's supposed to be calling.

    0 讨论(0)
  • 2021-01-17 12:27

    In Brief, you can write the code without event listener, but using event listener help other to use the same code as library.

    0 讨论(0)
提交回复
热议问题