# Events And Listeners

# Introduction

ExpressWebJs events provides a simple observer implementation, allowing you to subscribe and listen for events in your application. Event classes are typically stored in the App/Events directory, while their listeners are stored in App/Listeners. Don't worry if you don't see these directories in your application as they will be created for you as you generate events and listeners using Maker console commands.

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.

# Defining Events

You can create events in ExpressWebJs via the Maker console command followed by your event name.

  ts-node maker make-events SalesOrder

This will create a SalesOrder_event.ts class in our App/Events directory.

import Emitter from "Elucidate/Emitter";

export class SalesOrder {
  constructor<T>(private arg: T) {
    this.listenOn();
    Emitter.emitEvent("SalesOrder");
  }

  /**
   * Get the listener to listen to the event.
   */
  private async listenOn() {
    //
  }
}

# Defining Listeners

Next, lets's generate our salesOrder event listener with the following Maker command

   ts-node maker make-listener SalesOrderListener
import Emitter from "Elucidate/Emitter";

export class SalesOrderListener {
  constructor<T>(eventName: string, args: T) {
    Emitter.bind(eventName, () => {
      //Do something
    });
  }
}

Event listeners receive event instances in constructor. Within the constructor, you may perform any actions necessary to respond to the event.

# Binding Listeners To Events

Now that our SalesOrder event and listener is ready, we need to bind our SalesOrder listener to our SalesOrder event. We do that in our SalesOrder event in App/Events/SalesOrder_event.ts file:

import Emitter from "Elucidate/Emitter";
import SalesOrderListener from "App/Listeners/SalesOrder_listener";

export class SalesOrder {
  private eventName = "SalesOrder";

  constructor<T>(private args: T) {
    this.listenOn();
    Emitter.emitEvent(this.eventName);
  }

  /**
   * Get the listener to listen to the event.
   */
  public async listenOn() {
    new SalesOrderListener(this.eventName, this.args);
  }
}

We can bind multiple listeners to an event. Let's say we have SlackNotification listener we want to add to SalesOrder event, we can do that by adding it in the listenOn method.

"use strict";
import Emitter from "Elucidate/Emitter";
import SalesOrderListener from "App/Listeners/SalesOrder_listener";
import SlackNotificationListener from "App/Listeners/SlackNotification_listener";

class SalesOrder {
  private eventName = "SalesOrder";

  constructor<T>(private args: T) {
    this.listenOn();
    Emitter.emitEvent(this.eventName);
  }

  /**
   * Get the listener to listen to the event.
   */
  public async listenOn() {
    new SalesOrderListener(this.eventName, this.args);
    new SlackNotificationListener(this.eventName, this.args);
  }
}

# Using Events

Now that we have our event and listeners setup, let's use our event in our Controller, Service or any where in our application.

import SalesOrder_event from "App/Events/SalesOrder_event";
import SalesModel from "App/Model/Sales_model";
import { Request, Response } from "Config/http";
import { BaseController } from "./BaseController";

export class SalesController extends BaseController {
  store = async (req: Request, res: Response) => {
    try {
      let savedSales = await SalesModel.query().insert(req.body);
      new SalesOrder_event(savedSales);
      return this.response.OK(res, result);
    } catch (error) {
      return this.response.EXPECTATION_FAILED(res, error);
    }
  };
}