---
title: "TeqFW: Events basic"
description: "JavaScript, который является основным языком для создания teq-приложений, очень хорошо подходит для асинхронного программирования. В асинхронном программировании “события” играют о"
date: 2022-01-05
---

JavaScript, который является основным языком для создания
`teq`-приложений, очень хорошо подходит для асинхронного
программирования. В асинхронном программировании “*события*” играют
очень важную роль. В этой публикации я в очень общем виде описываю,
каким образом “*события*” используются в [Tequila
Framework](https://wiredgeese.com/%D1%87%D1%82%D0%BE-%D1%82%D0%B0%D0%BA%D0%BE%D0%B5-teqfw-208d5938205).

## Что такое “событие”

Событие — это значимое изменение состояния приложения (например,
“*пользователь аутентифицирован*”). С событием обязательно связаны некие
данные (“*идентификатор пользователя*”). Событие возникает, как
результат выполнения некоторого действия (“*проверка входного имени и
пароля и сопоставление их идентификатору пользователя*”) и само является
причиной для выполнения других действий (“*загрузка профиля
пользователя*”).

<figure>
<img src="/medium/img/541b01dfbe6b/image-01.png" alt="Image 2" />
</figure>

Итого, в самом простом случае мы имеем два функциональных объекта и один
дата-объект: `Event Producer` изменяет состояние приложения и генерирует
сообщение о событии (`Event Message`), передаваемое одному или
нескольким `Event Handler`’ам, которые реагируют на изменение состояния.

Событие прежде всего характеризуется своим типом (например, `onClick`) и
связанным с ним набором данных (например,
[MouseEvent](https://www.w3schools.com/jsref/obj_mouseevent.asp)).

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

## Локальные и трансграничные события

`Teq`-приложение, как правило, состоит из двух частей — фронта (в
браузере) и бэка (`nodejs`-приложение на сервере). Если и генератор
события, и обработчик находятся в пределах одной части (оба на фронте
или оба на бэке), то такое событие считается локальным. Если в разных
частях — трансграничным.

Сообщения о трансграничных событиях передаются по интернету в текстовом
виде (JSON) и должны содержать только такие данные, которые могут быть
сериализованы в JSON и десериализованы из него без потерь. Сообщения о
локальных событиях находятся в пределах выполнения одного программного
процесса и к ним подобные ограничения не применяются.

## Наименование событий

Имя события (его тип) должно быть уникально в пределах всего приложения.
Так как в `teq`-приложениях используются
[namespace](https://wiredgeese.com/teqfw-namespaces-26eee644615a)’ы, то
вполне естественным является решение, когда отдельному событию
соответствует отдельный `es6`-модуль, логическое имя которого и является
именем события:

- `Vnd_Plug_Front_Event_Net_Status_Changed` : локальное событие фронта;
- `Vnd_Plug_Back_Event_Sale_Order_Registered` : локальное событие бэка;
- `Vnd_Plug_Shared_Event_Front_Sale_Order_Confirmed` : трансграничное
  событие, происходящее на фронте;
- `Vnd_Plug_Shared_Event_Back_Sale_Order_Registered` : трансграничное
  событие, происходящее на бэке;

`es6`-модуль помимо имени события
[инкапсулирует](https://github.com/teqfw/core/blob/main/src/Shared/Api/IEvent.mjs)
также структуру данных
([DTO](https://wiredgeese.com/teqfw-dto-d19032d73303)) для сообщения о
событии.

## Обработка локальных событий

Локальные события генерируются и обрабатываются в рамках одного
вычислительного процесса. Генератор событий должен имплементировать
методы для извещения обработчиков о событии, добавления и удаления
обработчиков событий:

```js
class EventProducer {
  emit(eventName, message) {}
  subscribe(eventName, handler) {}
  unsubscribe(subscription) {}
}
```

Подписчик сообщает генератору, на какое его событие он хочет получать сообщения, и предоставляет генератору обработчик для реакции на событие. Когда генератор фиксирует наступление нужного события, он отправляет сообщение с деталями события обработчику:

<figure>
<img src="/medium/img/541b01dfbe6b/image-02.png" alt="Image 3" />
</figure>

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

## Обработка трансграничных событий

В трансграничных событиях генератор событий находится на одной стороне
(фронт или бэк), а подписчик — на другой (бэк или фронт). Между ними —
нестабильный канал связи (поскольку мы говорим за мобильные
`web`-приложения). Событие, которое происходит на фронте, генерирует
сообщение, которое доставляется на бэк, и уже там соответствующий
обработчик выполняет с ним необходимые действия:

<figure>
<img src="/medium/img/541b01dfbe6b/image-03.png" alt="Image 4" />
</figure>

Генератор событий отправляет сообщения в очередь, которая мониторит
состояние канала связи между сторонами и отправляет сообщения на другую
сторону по мере возможности. На второй стороне находится представитель
(“*посольство*”), который позволяет через него подписаться на любое
событие, происходящее на “*той*” стороне. Как только представитель
получает сообщение о событии через сеть, он перенаправляет его
соответствующему обработчику.

Принцип обработки идентичен как для направления “*фронт — бэк*”, так и
для обратного направления.

## Резюме

Событийно-ориентированная архитектура заложена в основы языка JavaScript
и она очень хорошо подходит для асинхронной обработки данных в условиях
случайным образом изменяемой среды выполнения. Но
событийно-ориентированная архитектура считается сложной для понимания
происходящих в ней процессов, поэтому “*событийно-ориентированные*”
приложения должны обеспечивать необходимый уровень логирования как на
серверной стороне, так и на клиентах.
