diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:43:23 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:43:23 -0500 |
commit | 218934fa2ed1c702a6d3923d2aa2cc6b43c48684 (patch) | |
tree | a9ef8ac1e1b8fe4207b6d64d3841bfb8990b6fd0 /files/zh-tw/web/api/server-sent_events | |
parent | 074785cea106179cb3305637055ab0a009ca74f2 (diff) | |
download | translated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.tar.gz translated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.tar.bz2 translated-content-218934fa2ed1c702a6d3923d2aa2cc6b43c48684.zip |
initial commit
Diffstat (limited to 'files/zh-tw/web/api/server-sent_events')
-rw-r--r-- | files/zh-tw/web/api/server-sent_events/index.html | 115 | ||||
-rw-r--r-- | files/zh-tw/web/api/server-sent_events/using_server-sent_events/index.html | 202 |
2 files changed, 317 insertions, 0 deletions
diff --git a/files/zh-tw/web/api/server-sent_events/index.html b/files/zh-tw/web/api/server-sent_events/index.html new file mode 100644 index 0000000000..bb72cb3f93 --- /dev/null +++ b/files/zh-tw/web/api/server-sent_events/index.html @@ -0,0 +1,115 @@ +--- +title: Server-sent events +slug: Web/API/Server-sent_events +translation_of: Web/API/Server-sent_events +--- +<p>網頁一般來說是由客戶端向伺服器請求資料. 藉由 server-sent 事件, 伺服器在任何時候都可以向客戶端推送資料. 即將推送進來的訊息可以自客戶端上做 <em><a href="/en-US/docs/DOM/event" title="DOM/Event">Events</a> + data </em>處理.</p> + +<table class="topicpage-table"> + <tbody> + <tr> + <td> + <h2 class="Documentation" id="Documentation" name="Documentation">文件</h2> + + <dl> + <dt>使用 <a href="/en-US/docs/Server-sent_events/Using_server-sent_events" title="Server-sent events/Using server-sent events">server-sent events</a></dt> + <dd>有關如何在伺服器端和客戶端使用 server-sent 事件的教學文章.</dd> + <dt>參考 <a href="/en-US/docs/Server-sent_events/EventSource" title="Server-sent events/EventSource">EventSource</a></dt> + <dd>關於客戶端的 EventSource API.</dd> + </dl> + + <p><span class="alllinks"><a href="/en-US/docs/tag/Server-sent_events" title="tag/Server-sent events">瀏覽全部...</a></span></p> + </td> + <td> + <h2 class="Tools" id="Tools" name="Tools">工具</h2> + + <ul> + <li>Remy Sharp’s <a class="link-https" href="https://github.com/remy/polyfills/blob/master/EventSource.js">EventSource polyfill</a></li> + <li>Yaffle’s <a class="link-https" href="https://github.com/Yaffle/EventSource" title="https://github.com/Yaffle/EventSource">EventSource polyfill</a></li> + <li>Rick Waldron’s <a class="link-https" href="https://github.com/rwldrn/jquery.eventsource">jquery plugin</a></li> + </ul> + + <h2 class="Related_Topics" id="Related_Topics" name="Related_Topics">相關主題</h2> + + <ul> + <li><a href="/en-US/docs/AJAX" title="AJAX">AJAX</a>, <a href="/en-US/docs/JavaScript" title="JavaScript">JavaScript</a>, <a href="/en-US/docs/WebSockets" title="WebSockets">WebSockets</a></li> + </ul> + </td> + </tr> + </tbody> +</table> + +<h2 id="參見">參見</h2> + +<ul> + <li>A <a href="http://hacks.mozilla.org/2011/06/a-wall-powered-by-eventsource-and-server-sent-events/" title="http://hacks.mozilla.org/2011/06/a-wall-powered-by-eventsource-and-server-sent-events/">Twitter like application</a> powered by server-sent events and <a class="link-https" href="https://github.com/mozilla/webowonder-demos/tree/master/demos/friends%20timeline" title="https://github.com/mozilla/webowonder-demos/tree/master/demos/friends timeline">its code on Github</a>.</li> + <li><a href="http://dsheiko.com/weblog/html5-and-server-sent-events" title="http://dsheiko.com/weblog/html5-and-server-sent-events">HTML5 and Server-sent events</a></li> + <li><a href="http://rajudasa.blogspot.in/2012/05/html5-server-sent-events-using-aspnet.html" title="http://rajudasa.blogspot.in/2012/05/html5-server-sent-events-using-aspnet.html">Server-sent events using Asp.Net</a></li> +</ul> + +<h2 id="規範">規範</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('Server-sent events')}}</td> + <td>{{Spec2('Server-sent events')}}</td> + <td>Initial definition.</td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>EventSource support</td> + <td>9</td> + <td>{{CompatGeckoDesktop("6.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>11</td> + <td>5</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>EventSource support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> diff --git a/files/zh-tw/web/api/server-sent_events/using_server-sent_events/index.html b/files/zh-tw/web/api/server-sent_events/using_server-sent_events/index.html new file mode 100644 index 0000000000..92433f4f18 --- /dev/null +++ b/files/zh-tw/web/api/server-sent_events/using_server-sent_events/index.html @@ -0,0 +1,202 @@ +--- +title: 使用 server-sent 事件 +slug: Web/API/Server-sent_events/Using_server-sent_events +tags: + - Advanced + - Communication + - DOM + - EventSource + - Guide + - SSE + - Server Sent Events + - Server-Sent-Event +translation_of: Web/API/Server-sent_events/Using_server-sent_events +--- +<p>{{DefaultAPISidebar("Server Sent Events")}}</p> + +<div class="summary"> +<p>開發一個使用 server-sent 事件的網頁應用程式很簡單。在伺服器端只需要一些的程式碼與網頁串流事件,而客戶端這邊的處理進入事件的部分幾乎跟 <a href="/zh-TW/docs/Web/API/WebSockets_API">websockets</a> 一樣。這是一種單向的連線,所以你無法從客戶端向伺服器傳送事件。</p> +</div> + +<h2 id="從伺服器端接收事件">從伺服器端接收事件</h2> + +<p>server-sent event API 包含在 {{domxref("EventSource")}} 介面;為了與伺服器端開啟連線並接收事件,需要建立帶有產生事件 script URL 的 {{domxref("EventSource")}} 物件。例如:</p> + +<pre class="brush: js notranslate">const evtSource = new EventSource("ssedemo.php");</pre> + +<p>如果事件產生的 script 在不同源的伺服器上,在建立 {{domxref("EventSource")}} 物件時需要同時提供 URL 和第二個參數作為選項設定。假設客戶端的 script 伺服於 <code>example.com</code> :</p> + +<pre class="brush: js notranslate">const evtSource = new EventSource("//api.example.com/ssedemo.php", { withCredentials: true } );</pre> + +<p>當你完成初始化事件來源後,你就可以透過新增 {{event("message")}} 事件的處理器來開始監聽來自伺服器的訊息:</p> + +<pre class="brush: js notranslate">evtSource.onmessage = function(event) { + const newElement = document.createElement("li"); + const eventList = document.getElementById("list"); + + newElement.innerHTML = "message: " + event.data; + eventList.appendChild(newElement); +} +</pre> + +<p>上述的程式碼會監聽進入的訊息(這裡來自伺服器的通知沒有指明 <code>event</code> 欄位,所以統一用 <code>onmessage</code> 處理即可)並且把訊息的文字附加到 document 的清單。</p> + +<p>你也可以利用 <code>addEventListener()</code> 監聽事件:</p> + +<pre class="brush: js notranslate">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); +}); +</pre> + +<p>上述的程式碼大同小異,不同之處在於若伺服器傳送了 <code>event</code> 欄位值為「ping」的訊息時它就會把 <code>data</code> 欄位的值解析為 JSON 並輸出到畫面上。</p> + +<div class="blockIndicator warning"> +<p>當連線不是透過<strong> HTTP/2</strong> 時,SSE 會受到最大連線數限制所苦,尤其當開啟多個分頁。每個瀏覽器有自己的限制數而且被限制在很低的數量(6)。這個問題已經被 <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=275955" rel="noreferrer">Chrome</a> 和 <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=906896" rel="noreferrer">Firefox</a> 標註為「Won't fix」(不修復)。限制是基於每個瀏覽器 + 網域,也就是說你可以針對 www.example1.com 網域在所有的分頁中開啟六個 SSE 連線,另一個網域 www.example2.com 也可以開啟六個(根據 <a href="https://stackoverflow.com/a/5326159/1905229">Stackoverflow</a>)。當使用 HTTP/2 時最大同時 <em>HTTP streams</em> 連線數是由伺服器和客戶端之間協調(預設 100)。</p> +</div> + +<h2 id="從伺服器發送事件">從伺服器發送事件</h2> + +<p>由伺服器端所發送的事件需要使用 <code>text/event-stream</code> 的 MIME 類型回應。每一個通知皆由一組文字組成並由一對換行結尾。如何處理事件串流的格式,請參考 {{ anch("Event stream format") }} 。</p> + +<p>下面是一個 {{Glossary("PHP")}} 範例:</p> + +<pre class="brush: php notranslate">date_default_timezone_set("America/New_York"); +header("Cache-Control: no-cache"); +header("Content-Type: text/event-stream"); + +$counter = rand(1, 10); +while (true) { + // 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(); + + // Break the loop if the client aborted the connection (closed the page) + + if ( connection_aborted() ) break; + + sleep(1); +} +</pre> + +<p>上述的程式碼會在每秒產生一個類型為「ping」的事件。每一個事件的資料是一個 JSON 物件,內容為事件產生時的 ISO 8601 時間戳。同時會隨機發送一個簡易訊息(沒有事件類型)。<br> + 迴圈的執行會獨立於連線的狀態,,所以在迴圈裡必須檢查連線的狀態,若斷線了要關閉連線(譬如,客戶端關閉了網頁)。</p> + +<div class="note"> +<p><strong>備註:</strong> 你可以從下列的 Github 文章中找到包含本文所使用程式碼的完整範例 —— 參考 <a href="https://github.com/mdn/dom-examples/tree/master/server-sent-events">Simple SSE demo using PHP.</a></p> +</div> + +<h2 id="錯誤處理">錯誤處理</h2> + +<p>當錯誤發生時(譬如網路逾時或有關<a href="/zh-TW/docs/Web/HTTP/CORS">存取控制</a>的問題)會產生錯誤事件。你可以透過對 <code>EventSource</code> 物件實作 <code>onerror</code> 回呼的方式採取程式化的處理:</p> + +<pre class="brush: js notranslate">evtSource.onerror = function(err) { + console.error("EventSource failed:", err); +}; +</pre> + +<h2 id="關閉事件串流">關閉事件串流</h2> + +<p>預設的情況下,如果客戶端和伺服器的連線關閉則連線會被重啟。連線的關閉會伴隨著 <code>.close()</code> 方法的執行。</p> + +<pre class="notranslate">evtSource.close();</pre> + +<h2 id="事件串流(Event_Stream)格式">事件串流(Event Stream)格式</h2> + +<p>事件串流是個簡易的文字資料串流,內容必須以 UTF-8 格式編碼。在事件串流中,不同的訊息以一對換行符號做區隔。若要撰寫註解,則要在該行的開頭加上冒號(:)。</p> + +<div class="note"><strong>備註:</strong> 註解將有助於防止連線逾時;伺服器端可以定時發送註解以維持連線活著。</div> + +<p>每一個訊息是由一到多列的欄位所組成的文字。每個欄位依序由欄位的名稱、冒號、該欄位的文字內容所組合而成。</p> + +<h3 id="欄位">欄位</h3> + +<p>每隔訊息皆可以由下列的欄位組合而成,每個欄位以換行做為區隔:</p> + +<dl> + <dt><code>event</code></dt> + <dd>事件的類型。如果有指定則在瀏覽器端會對該事件名稱的監聽器發布事件;網頁的原始碼必須使用 <code>addEventListener()</code> 來監聽已命名的事件。 <code>onmessage</code> 處理器只有在訊息沒有指定事件名稱時才會被呼叫。</dd> + <dt><code>data</code></dt> + <dd>訊息的資料欄位。當 EventSource 連續接收到多列以 <code>data:</code> 開頭的內容;<a href="http://www.w3.org/TR/eventsource/#dispatchMessage">它會串接這些內容</a>並為每一列插入一個換行字元。最後的換行會被移除。</dd> + <dt><code>id</code></dt> + <dd>{{domxref("EventSource")}} 物件的最新一個事件 ID 。</dd> + <dt><code>retry</code></dt> + <dd>當嘗試傳送事件時重新連線的時間。這個值必須是整數,單位是毫秒,作為重新連線的時間。若指定是非整數則這個欄位會被忽略。</dd> +</dl> + +<p>除上述的幾個欄位,其他欄位均會被忽略。</p> + +<div class="note"><strong>備註:</strong>如果某列的內容沒有包含冒號,則該列的內容都會被視為欄位名稱及空字串的欄位值。</div> + +<h3 id="範例">範例</h3> + +<h4 id="Data-only_訊息">Data-only 訊息</h4> + +<p>在下列的範例中,共發送了三個訊息。第一個是註解,因其以冒號開頭。如之前提到的,對不會持續發送訊息的情境下,這將有助於維持連線的存續。</p> + +<p>第二則訊息包含了 data 欄位及「some text」的值。第三則訊息包含了 data 欄位及「another message\nwith two lines」。注意在內容所出現的換行符號。</p> + +<pre class="notranslate">: this is a test stream + +data: some text + +data: another message +data: with two lines +</pre> + +<h4 id="命名事件">命名事件</h4> + +<p>這個範例傳送了一些命名的事件。每一個事件都被指定了 <code>event</code> 欄位並且 <code>data</code> 欄位也有相應的 JSON 字串作為客戶端回應事件所需的資料。 <code>data</code> 欄位的內容可以是任何的字串;它並沒有強制必須以 JSON 的格式撰寫。</p> + +<pre class="notranslate">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."} +</pre> + +<h4 id="混合及配對">混合及配對</h4> + +<p>你並非一定只能用未命名訊息或已分類的事件;實際上你可以在單一的事件中把它們混合在一起。</p> + +<pre class="notranslate">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."}</pre> + +<div> +<h3 id="EventSource"><code>EventSource</code></h3> + +<div> + + +<p>{{Compat("api.EventSource")}}</p> +</div> +</div> |