Программирование, управляемое событиями, — это парадигма программирования, которая фокусируется на потоке событий и обработке этих событий. Вот краткое описание ключевых концепций событийно-ориентированного программирования:

  1. События. События представляют собой события или изменения в системе, такие как взаимодействие с пользователем, системные уведомления или обновления данных. События могут быть инициированы внешними факторами или генерироваться внутри программы.
  2. Обработчики событий. Обработчики событий, также известные как прослушиватели событий или обратные вызовы, представляют собой функции, которые реагируют на определенные события. Они связаны с событиями и выполняются, когда происходит соответствующее событие.
  3. Цикл событий. Цикл событий является основным компонентом программирования, управляемого событиями. Он постоянно проверяет события и отправляет их соответствующим обработчикам событий. Это гарантирует, что события обрабатываются асинхронно, и позволяет программе одновременно реагировать на несколько событий.
  4. Излучатель/диспетчер событий. Излучатель или диспетчер событий — это механизм или объект, отвечающий за управление событиями и уведомление зарегистрированных обработчиков событий при возникновении событий. Это облегчает общение и координацию между производителями событий и потребителями событий.
  5. Публикация-подписка (Pub/Sub): Pub/Sub — это шаблон обмена сообщениями, обычно используемый в системах, управляемых событиями. Издатели событий или издатели создают события, не зная о потребителях событий или подписчиках. Подписчики регистрируют свой интерес к определенным событиям и получают уведомления, когда эти события публикуются.
  6. Обратные вызовы и промисы. Обратные вызовы и промисы — это распространенные шаблоны, используемые в программировании, управляемом событиями, для обработки асинхронных операций. Обратные вызовы — это функции, которые передаются в качестве аргументов для выполнения после завершения операции. Обещания обеспечивают более структурированный подход к обработке асинхронных операций, позволяя лучше обрабатывать ошибки и связывать операции в цепочки.

Программирование, управляемое событиями, позволяет разрабатывать отзывчивые и интерактивные системы, позволяя разработчикам эффективно обрабатывать события и реагировать на них. Он широко используется в различных областях, включая пользовательские интерфейсы, сетевое взаимодействие, серверные приложения и системы реального времени.

Создание пользовательского генератора событий

class MyCustomEventEmitter {
  constructor() {
    this.events = new Map();
  }
  //Registering Event Listeners.
  on(eventName, cb) {
    if (this.events.has(eventName)) {
      this.events.get(eventName).push(cb);
    } else {
      this.events.set(eventName, [cb]);
    }
  }
  //Emitting Events
  emit(callbck, ...rest) {
    rest.forEach((eventX) => {
      if (this.events.has(eventX)) {
        this.events.get(eventX).forEach((callBkLists) => {
          callBkLists(null, eventX);
        });
      } else {
        callbck(`No any listeners for event: ${eventX}`, null);
      }
    });
  }
  //Removing Event Listeners
  off(eventName, cb) {
    if (this.events.has(eventName)) {
      this.events.delete(eventName);
    } else {
      cb("No any registered Events for ", eventName);
    }
  }
  //Listeners will listen for request Only One time.
  once(eventName, cb) {
    const wrapper = (...args) => {
      cb(...args);
      this.off(eventName, wrapper);
    };
    this.on(eventName, wrapper);
  }
  //retrieving all registered
  getAllListeners() {
    return this.events;
  }
}

const myEvent = new MyCustomEventEmitter();

myEvent.once("msg", (err, data) => {
  if (err) {
    console.log("Failed");
  } else {
    console.log("This runs only once");
  }
});
myEvent.on("idle", (err, data) => {
  if (err) {
    console.log("Failed");
  } else {
    console.log("registered eventName:", data);
  }
});
myEvent.emit(
  (err) => {
    if (err) {
      console.log(err);
    }
  },
  "msg",
  "msg",
  "idle",
  "idle"
);
//Output in console.
This runs only once
No any listeners for event: msg
registered eventName: idle
registered eventName: idle

Регистрация прослушивателей событий

Для регистрации прослушивателей событий мы используем метод on. Он принимает eventName и функцию обратного вызова (cb). Метод on проверяет, существует ли уже eventName на карте events. Если она существует, функция обратного вызова cb добавляется в массив слушателей для этого события. Если eventName является новым, новый массив, содержащий функцию обратного вызова, устанавливается в качестве значения для этого ключа события на карте.

Отправка событий

Чтобы генерировать события и запускать связанные слушатели, мы используем метод emit. Он принимает функцию обратного вызова (callbck) и любое количество дополнительных аргументов (rest). Метод emit перебирает каждое событие, указанное в rest. Для каждого события он проверяет, зарегистрированы ли какие-либо слушатели для этого события, используя this.events.has(eventX). Если слушатели существуют, он выполняет каждый слушатель, вызывая их с помощью callBkLists(null, eventX). Если прослушиватели не зарегистрированы, он вызывает предоставленную функцию обратного вызова с сообщением об ошибке.

Удаление прослушивателей событий

Чтобы удалить прослушиватели событий, мы используем метод off. Он принимает eventName и функцию обратного вызова (cb). Метод off сначала проверяет, существует ли eventName на карте events. Если это так, событие удаляется с карты с помощью this.events.delete(eventName). Если eventName не найден, он вызывает предоставленную функцию обратного вызова с сообщением об ошибке.

Прослушивание событий один раз

Чтобы зарегистрировать прослушиватели, которые прослушивают события только один раз, мы используем метод once. Он принимает eventName и функцию обратного вызова (cb). Метод once создает функцию-оболочку, которая выполняет исходную функцию обратного вызова (cb), а затем автоматически удаляет себя, вызывая this.off(eventName, wrapper). Затем функция-оболочка регистрируется как прослушиватель событий, используя this.on(eventName, wrapper).

Получение всех зарегистрированных слушателей

Чтобы получить всех зарегистрированных прослушивателей, мы используем метод getAllListeners. Метод getAllListeners просто возвращает карту events, содержащую все зарегистрированные прослушиватели событий.

Заключение

В этом сообщении блога мы рассмотрели создание собственного генератора событий в JavaScript. Мы рассмотрели, как регистрировать прослушиватели событий, генерировать события, удалять прослушиватели событий, однократно прослушивать события и извлекать все зарегистрированные прослушиватели. С помощью этого настраиваемого эмиттера событий у вас есть возможность гибко обрабатывать события в ваших приложениях JavaScript.