Как инициировать события EventSource SSE? - PullRequest
3 голосов
/ 05 марта 2012

Я недавно обнаружил EventSource, у YUI3 есть модуль Gallery для нормализации и аварийного поведения, это то, что я решил использовать в своем примере, так как уже использую этот фреймворк.

Итак, яИскал много, прочитал много блогов, постов и примеров, каждый из которых показывает примерно одно и то же: Как настроить основные события SSE.Теперь у меня есть 6 примеров запуска событий open / message / error / close.

То, чего у меня нет (на что я надеялся эта ссылка собиралась дать мне), этоПример того, как запускать события SSE, которые более полезны для моего приложения, я пробую один, называемый «update».

Вот моя базовая тестовая страница: http://codefinger.co.nz/public/yui/eventsource/test.php (это также может бытьhtml-файл, здесь пока нет php-кода)

А вот «message.php» в конструкторе EventSource:

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache'); // recommended to prevent caching of event data.

/**
 * Constructs the SSE data format and flushes that data to the client.
 *
 * @param string $id Timestamp/id of this connection.
 * @param string $msg Line of text that should be transmitted.
 */
function sendMsg($id, $msg) {
  echo "id: $id" . PHP_EOL;
  echo "data: $msg" . PHP_EOL;
  echo PHP_EOL;
  ob_flush();
  flush();
}
while(true) {
  $serverTime = time();
  sendMsg($serverTime, 'server time: ' . date("h:i:s", time()));
  sleep(10);
}

// I was hoping calling this file with a param might allow me to fire an event,
// which it does dutifully, but no browsers register the 'data : update' - though
// I do see the response in Firebug.
if( $_REQUEST['cmd'] ){
    sendMsg($serverTime, $_REQUEST['cmd'] );
}
?>

Из приведенного выше живого примера вы можете видеть, чтоЯ пытался использовать модуль io YUI для отправки запроса с параметром для запуска события «обновление», когда я нажимаю кнопку «обновить».Кажется, это работает, как вы можете видеть на панели Net в Firebug, но мое событие не обрабатывается (я понимаю, что приведенный выше скрипт снова запустит этот цикл, я просто хочу обработать свое событие в подключенных браузерах, а затем удалю/cleanup).

Я делаю эту часть неправильно?Или есть что-то более фундаментальное, что я делаю не так?Я пытаюсь выдвинуть события в ответ на изменение состояния моего пользовательского интерфейса.

Этот SO вопрос , похоже, подошел близко, @tomfumb прокомментировал, что его следующий вопрос будет "как отправитьновые события для клиента после установления первоначального соединения - теперь я вижу, что PHP просто никогда не должен останавливаться ».Но, конечно, я бы отправлял события только по мере их поступления ... и не непрерывно ...

1 Ответ

2 голосов
/ 11 марта 2012

В вашем подходе есть несколько проблем:

  1. Код на стороне сервера, который читает параметр cmd, недоступен из-за бесконечного цикла, который отправляет данные о событиях клиенту.
  2. Вы пытаетесь отправить событие с клиента на сервер.Это в названии спецификации - Server-Sent Events - сервер является отправителем, а клиент - получателем событий.У вас есть варианты здесь:
    1. Используйте соответствующую спецификацию для задания под названием Веб-сокеты , который представляет собой API двусторонней связи
    2. Напишите логику, которая делает возможным тип связи, возможный

Если вы решите остаться с SSE API, я вижу два возможных сценария

  1. Повторное использование одного и того же соединения с источником событий и сохранение пула соединений на сервере.Когда пользователь отправляет последующий XMLHttpRequest с помощью команды update, получает соединение EventSource из пула, созданного этим посетителем, и отправляет с ним ответ, в котором указывается пользовательский тип события, типом по умолчанию является message.Важно избегать вхождения в бесконечный цикл, который мог бы создать другое соединение EventSource с клиентом, но клиент не обрабатывает его, потому что он сделал запрос с XMLHttpRequest, а не с EventSource.
  2. Делать все запросы с EventSource.Прежде чем сделать новый запрос EventSource, закройте предыдущий - вы можете сделать это с клиента или с сервера.На сервере проверьте параметры и затем отправьте данные клиенту.

Также вы можете использовать XMLHttpRequest с (длинным) опросом и, таким образом, избежать необходимости использования EventSource.Из-за простоты вашего примера я не вижу причин смешивать два типа запросов.

...