Программирование, управляемое событиями, — это парадигма программирования, которая фокусируется на потоке событий и обработке этих событий. Вот краткое описание ключевых концепций событийно-ориентированного программирования:
- События. События представляют собой события или изменения в системе, такие как взаимодействие с пользователем, системные уведомления или обновления данных. События могут быть инициированы внешними факторами или генерироваться внутри программы.
- Обработчики событий. Обработчики событий, также известные как прослушиватели событий или обратные вызовы, представляют собой функции, которые реагируют на определенные события. Они связаны с событиями и выполняются, когда происходит соответствующее событие.
- Цикл событий. Цикл событий является основным компонентом программирования, управляемого событиями. Он постоянно проверяет события и отправляет их соответствующим обработчикам событий. Это гарантирует, что события обрабатываются асинхронно, и позволяет программе одновременно реагировать на несколько событий.
- Излучатель/диспетчер событий. Излучатель или диспетчер событий — это механизм или объект, отвечающий за управление событиями и уведомление зарегистрированных обработчиков событий при возникновении событий. Это облегчает общение и координацию между производителями событий и потребителями событий.
- Публикация-подписка (Pub/Sub): Pub/Sub — это шаблон обмена сообщениями, обычно используемый в системах, управляемых событиями. Издатели событий или издатели создают события, не зная о потребителях событий или подписчиках. Подписчики регистрируют свой интерес к определенным событиям и получают уведомления, когда эти события публикуются.
- Обратные вызовы и промисы. Обратные вызовы и промисы — это распространенные шаблоны, используемые в программировании, управляемом событиями, для обработки асинхронных операций. Обратные вызовы — это функции, которые передаются в качестве аргументов для выполнения после завершения операции. Обещания обеспечивают более структурированный подход к обработке асинхронных операций, позволяя лучше обрабатывать ошибки и связывать операции в цепочки.
Программирование, управляемое событиями, позволяет разрабатывать отзывчивые и интерактивные системы, позволяя разработчикам эффективно обрабатывать события и реагировать на них. Он широко используется в различных областях, включая пользовательские интерфейсы, сетевое взаимодействие, серверные приложения и системы реального времени.
Создание пользовательского генератора событий
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.