server sent event基本上是由伺服器端單向送出資料的溝通機制,類似server push。這是一個與http相容的方法,只需要伺服器端送出特定的header、content-type及固定格式的內容就可以做到。類似的技術可以參考:

http://en.wikipedia.org/wiki/Push\_technology
在瀏覽器端使用server sent event的物件叫做EventSource:

[Constructor(in DOMString url)]
interface EventSource {
  readonly attribute DOMString URL;
  // ready state
  const unsigned short CONNECTING = 0;
  const unsigned short OPEN = 1;
  const unsigned short CLOSED = 2;
  readonly attribute unsigned short readyState;
  // networking
           attribute Function onopen;
           attribute Function onmessage;
           attribute Function onerror;
  void close();
EventSource implements EventTarget;

使用方式很簡單,當然伺服器要準備好一個送出event stream的URL,然後使用new EventSource(URL)來產生一個物件,利用他的onmessage來監聽事件:

<html lang="zh-TW">
<meta http-equiv="Content-Type" content="text/html; charset=utf8">
<style>
	div {
		border: solid 2px #336699;
		margin: 10px;
		padding: 5px;
		border-radius: 5px;
		vertical-align: top;
		text-align: center;
		display: inline-block;
	.container {
		background: #88BBFF;
		width: 520px;
	.msg {
		background: #99CCFF;
		border: dotted 1px #4477AA;
		width: 480px;
		margin: 0px;
		text-align: left;
		font-size: 12px;
</style>
<script>
function init() {
	var es = new EventSource('test634.php');
	es.addEventListener('message', function(e) {
		var str = '';
		str += '<li>[' + new Date() + ']: ';
		str += e.data + '</li>\n';
		document.getElementById('msg1').innerHTML += str;
	}, false);
</script>
	<div class="container">
		Returned Messages.
		<div id="msg1" class="msg"></div>
<script>
init();
</script>

伺服器端的php很簡單,只是每兩秒送出一個event...

header("Content-Type: text/event-stream"); flush(); $count = 0; while(true) { echo "data: " . "Server Sent Event round: " . $count . "\n\n"; $count++; flush(); sleep(2);

每當伺服器連續兩個換行,EventSource就會把之前送出的資料當成一個事件,觸發onmessage。

我的伺服器有設定php最長執行時間,所以大約跑14~15次就會timeout,重新啟動程式,不過不會影響瀏覽器端的執行(這其實不一定,要看程式的結構及邏輯是否會影響每次重頭執行時的邏輯正確性)

熟悉server push跟long poll的人,應該很熟悉這樣的scenario,我想這也是Server Sent Event的目的,不過使用它可以讓這個流程變得很簡單。

不過目前EventSource似乎只有在Chrome7及Safari上才能執行Orz,抓兩個執行畫面:

在寫PHP時需要注意,沒有使用flush()的話,內容會到程式結束才一次送出XD,所以上面的PHP程式中,我在header送出後及echo之後分別呼叫了一次flush(),讓伺服器分批送出內容。另外,由於Server Sent Event只支援UTF8編碼的資訊,所以伺服器端的程式送出的內容必須是UTF8編碼的。