使用 server-sent 事件

翻譯不完整。請協助 翻譯此英文文件

開發一個使用 server-sent 事件的網頁應用程式很簡單。在伺服器端只需要一些的程式碼與網頁串流事件,而客戶端這邊的處理方式和其他事件處理方式幾乎相同。

從伺服器端接收事件

server-sent event API 包含在  EventSource 接口;為了與伺服器端開啟連線並接收事件,需要創建一個標註伺服器腳本的  EventSource 物件。例如:

var evtSource = new EventSource("ssedemo.php");

If the event generator script is hosted on a different domain a new EventSource object should be created that specifies both the URI and options dictionary. 例如, assuming the client script is on example.com:

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

註: 使用 EventSource 並未被所有的瀏覽器支援. 請檢查瀏覽器的相容性.

當你建構好你的 event source,就可以開始監聽伺服器傳來的訊息:

evtSource.onmessage = function(e) {
  var newElement = document.createElement("li");
  
  newElement.innerHTML = "message: " + e.data;
  eventList.appendChild(newElement);
}

This code listens for incoming messages (that is, notices from the server that do not have an event field on them) and appends the message text to a list in the document's HTML.

你也可以利用 addEventListener() 監聽事件:

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

This code is similar, except that it will be called automatically whenever the server sends a message with the event field set to "ping"; it then parses the JSON in the data field and outputs that information.

從伺服器發送事件

The server-side script that sends events needs to respond using the MIME type text/event-stream. Each notification is sent as a block of text terminated by a pair of newlines. For details on the format of the event stream, see Event stream format.

下面是一個 PHP 範例:

date_default_timezone_set("America/New_York");
header("Content-Type: text/event-stream\n\n");

$counter = rand(1, 10);
while (1) {
  // Every second, sent 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_flush();
  flush();
  sleep(1);
}

The code above generates an event every second, with the event type "ping". Each event's data is a JSON object containing the ISO 8601 timestamp corresponding to the time at which the event was generated. At random intervals, a simple message (with no event type) is sent.

錯誤處理

When problems occur (such as a network timeout or issues pertaining to access control), an error event is generated. You can take action on this programmatically by  implementing the onerror callback on the EventSource object:

evtSource.onerror = function(e) {
  alert("EventSource failed.");
};

As of Firefox 22, it does not appear that there is any way to distinguish between different kinds of error events.

關閉事件串流

By default, if the connection between the client and server closes, the connection is reset. The connection is terminated with the .close() method.

evtSource.close();

事件串流(Event Stream)格式

Event stream 是個簡單的純文字檔。其必須以 UTF-8 格式編碼。在 Event stream 中,不同的訊息以一對換行符號做區分。若要撰寫註解,要在一行的開頭加上冒號(:)。

Note: The comment line can be used to prevent connections from timing out; a server can send a comment periodically to keep the connection alive.

Each message consists of one or more lines of text listing the fields for that message. Each field is represented by the field name, followed by a colon, followed by the text data for that field's value.

Fields

規格書中定義 Event Stream 以下欄位

event
The event's type. If this is specified, an event will be dispatched on the browser to the listener for the specified event name; the web site source code should use addEventListener() to listen for named events. The onmessage handler is called if no event name is specified for a message.
data
The data field for the message. When the EventSource receives multiple consecutive lines that begin with data:, it will concatenate them, inserting a newline character between each one. Trailing newlines are removed.
id
The event ID to set the EventSource object's last event ID value.
retry
The reconnection time to use when attempting to send the event. [What code handles this?] This must be an integer, specifying the reconnection time in milliseconds. If a non-integer value is specified the field is ignored.

除上述的幾個欄位,其他欄位均會被忽略。

註: If a line doesn't contain a colon the entire line is treated as the field name with an empty value string.

範例

Data-only messages

In the following example, there are three messages sent. The first is just a comment, since it starts with a colon character. As mentioned previously, this can be useful as a keep-alive if messages may not be sent regularly.

The second message contains a data field with the value "some text". The third message contains a data field with the value "another message\nwith two lines". Note the newline special character in the value.

: this is a test stream

data: some text

data: another message
data: with two lines 

命名地事件

This example sends some named events. Each has an event name specified by the event field, and a data field whose value is an appropriate JSON string with the data needed for the client to act on the event. The data field could, of course, have any string data; it doesn't have to be 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."}

Mixing and matching

You don't have to use just unnamed messages or typed events; you can mix them together in a single event stream.

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."}

瀏覽器相容性

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
EventSource support 9 6.0 (6.0) Not supported 11 5
Feature Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
EventSource support 42 ? ? 11.1 4

 

文件標籤與貢獻者

 最近更新: Shiyou,