From 074785cea106179cb3305637055ab0a009ca74f2 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:42:52 -0500 Subject: initial commit --- .../using_server-sent_events/index.html | 186 +++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 files/ru/web/api/server-sent_events/using_server-sent_events/index.html (limited to 'files/ru/web/api/server-sent_events/using_server-sent_events') diff --git a/files/ru/web/api/server-sent_events/using_server-sent_events/index.html b/files/ru/web/api/server-sent_events/using_server-sent_events/index.html new file mode 100644 index 0000000000..8aeb349c50 --- /dev/null +++ b/files/ru/web/api/server-sent_events/using_server-sent_events/index.html @@ -0,0 +1,186 @@ +--- +title: Using server-sent events +slug: Web/API/Server-sent_events/Using_server-sent_events +translation_of: Web/API/Server-sent_events/Using_server-sent_events +--- +

{{DefaultAPISidebar("Server Sent Events")}}

+ +
+

Разрабатывать web-приложения, использующие Server-Sent Events намного проще, чем с использованием websockets. Нужно всего лишь немного кода на стороне сервере, чтобы переправлять события web-приложению, но клиентская часть кода для обработки этих событий работает почти точно так же, как и для любых других событий.

+
+ +

Получение событий от сервера

+ +

Server-Sent Event API содержится внутри интерфейса {{domxref("EventSource")}}. Чтобы открыть соединение с сервером для начала записи событий, которые он присылает, необходимо создать новый объект EventSource, который будет указывать на URI скрипта, который создает события. Например:

+ +
const evtSource = new EventSource("ssedemo.php");
+ +

Если файл с генератором событий размещен на другом домене, то должен быть создан новый объект EventSource в который следует передать помимо URI еще и словарь опций. Например, если предположить, что клиентский скрипт находится на example.com:

+ +
const evtSource = new EventSource("//api.example.com/ssedemo.php", { withCredentials: true } ); 
+
+ +

Как только вы создали экземпляр EventSource, вы можете начать прослушивание сообщений с сервера, добавив обработчик для события {{event("message")}} :

+ +
evtSource.onmessage = function(event) {
+  const newElement = document.createElement("li");
+  const eventList = document.getElementById('list');
+
+  newElement.innerHTML = "message: " + event.data;
+  eventList.appendChild(newElement);
+}
+
+ +

Этот код прослушивает входящие сообщения (то есть уведомления от сервера, на которых нет поля event) и добавляет текст сообщения в список в HTML-документе.

+ +

Вы также можете прослушивать события, используя addEventListener():

+ +
evtSource.addEventListener("ping", function(event) {
+  const newElement = document.createElement("li");
+  const time = JSON.parse(event.data).time;
+
+  newElement.innerHTML = "ping at " + time;
+  eventList.appendChild(newElement);
+});
+ +

Этот код аналогичен коду выше, за исключением того, что он будет вызываться автоматически всякий раз, когда сервер отправляет сообщение с полем event, установленным в «ping»; затем он парсит JSON в поле data и выводит эту информацию.

+ +

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

+ +

Код на стороне сервера, который отправляет события, должен отвечать, используя MIME-тип text/event-stream. Каждое уведомление отправляется в виде блока текста, оканчивающегося парой новых строк (\n) . Подробнее о формате потока событий см.  {{ anch("Event stream format") }}.

+ +

{{Glossary("PHP")}} код, который мы используем для примера приведен ниже:

+ +
date_default_timezone_set("America/New_York");
+header('Cache-Control: no-cache');
+header("Content-Type: text/event-stream\n\n");
+
+$counter = rand(1, 10);
+while (1) {
+  // Every second, send a "ping" event.
+
+  echo "event: ping\n";
+  $curDate = date(DATE_ISO8601);
+  echo 'data: {"time": "' . $curDate . '"}';
+  echo "\n\n";
+
+  // Send a simple message at random intervals.
+
+  $counter--;
+
+  if (!$counter) {
+    echo 'data: This is a message at time ' . $curDate . "\n\n";
+    $counter = rand(1, 10);
+  }
+
+  ob_end_flush();
+  flush();
+  sleep(1);
+}
+
+ +

Приведенный выше код генерирует событие каждую секунду с типом события «ping». Данные каждого события - это объект JSON, содержащий метку времени ISO 8601, соответствующую дате, когда было сгенерировано событие. Через случайные интервалы отправляется простое сообщение (без типа event).

+ +
+

Примечание: Вы можете найти полный пример, который использует код, показанный в этой статье на GitHub - см. Simple SSE demo using PHP.

+
+ +

Обработка ошибок

+ +

Когда возникают проблемы (такие как тайм-аут ответа сети или проблемы, связанные с контролем доступа), тогда генерируется событие error. Вы можете обработать это событие программно, реализовав метод onerror для объекта EventSource:

+ +
evtSource.onerror = function(error) {
+  console.error("⛔ EventSource failed: ", error);
+};
+
+ +

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

+ +

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

+ +
evtSource.close();
+ +

Формат потока событий

+ +

Поток событий представляет из себя простой поток текста, который должен иметь кодировку UTF-8. Сообщения в потоке событий разделяются парой символов новой строки. Двоеточие, как первый символ строки считается комментарием и игнорируется.

+ +
Примечание: Строка комментария может использоваться, чтобы предотвратить тайм-аут соединений; сервер может периодически отправлять комментарий, чтобы поддерживать соединение.
+ +

Каждое сообщение содержит одну или более строчек текста, которые перечиляют поля этого сообщения. Каждое имеет свое имя, за которым следует двоеточие, после которого идут текстовые данные для значения этого поля. 

+ +

Поля

+ +

Каждое полученное сообщение имеет некоторую комбинацию следующих полей, по одному на строку:

+ +
+
event
+
Строка, идентифицирующая тип описанного события. Если event указан, то событие будет отправлено в браузер слушателю для указанного имени события. Исходный код сайта должен использовать addEventListener() для прослушивания именованных событий. Обработчик onmessage вызывается, если для сообщения не указано имя события.
+
data
+
Поле данных для сообщения. Когда EventSource получает несколько последовательных строк, начинающихся с data:, он объединяет их, вставляя символ новой строки между каждой из них. Последние переводы строки удаляются.
+
id
+
Идентификатор события для установки значения последнего ID события для объекта EventSource.
+
retry
+
Время переподключения, используемое при попытке отправить событие. Это должно быть целое число, указывающее время переподключения в миллисекундах. Если указано нецелое значение, поле игнорируется.
+
+ +

Другия названия полей игнорируются.

+ +
Примечание: If a line doesn't contain a colon, the entire line is treated as the field name with an empty value string.
+ +

Примеры

+ +

Сообщения с данными

+ +

В следующем примере отправлено три сообщения. Первый - это просто комментарий, так как он начинается с символа двоеточия. Как упоминалось ранее, это может быть полезно в качестве подтверждения активности, если сообщения могут отправляться не регулярно.

+ +

Второе сообщение содержит поле данных со значением «some text». Третье сообщение содержит поле данных со значением «another message \n with two lines». Обратите внимание на специальный символ новой строки в значении.

+ +
: this is a test stream
+
+data: some text
+
+data: another message
+data:
+
+ +

Именованные события

+ +

Данный пример отправляет именованные события. У каждого из них есть имя события, указанное в поле event, и поле data, значением которого является соответствующая строка JSON с данными, необходимыми для клиента, чтобы реагировать на событие. Поле data может, конечно, содержать любые строковые данные; это не обязательно должен быть JSON.

+ +
event: userconnect
+data: {"username": "bobby", "time": "02:33:48"}
+
+event: usermessage
+data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."}
+
+event: userdisconnect
+data: {"username": "bobby", "time": "02:34:23"}
+
+event: usermessage
+data: {"username": "sean", "time": "02:34:36", "text": "Bye, bobby."}
+
+ +

Смешивание и сопоставление

+ +

Вам не нужно использовать только неназванные сообщения или именованные события. Вы можете смешать их вместе в одном потоке событий.

+ +
event: userconnect
+data: {"username": "bobby", "time": "02:33:48"}
+
+data: Here's a system message of some kind that will get used
+data: to accomplish some task.
+
+event: usermessage
+data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."}
+ +

Совместимость с браузерами

+ +
+

EventSource

+ +
+ + +

{{Compat("api.EventSource")}}

+
+
-- cgit v1.2.3-54-g00ecf