HTML5で開発している新しいWebサイトにサーバー側イベントを提供するために、nodejsサーバーを開発しています。
サーバーに telnet で接続すると、正しく動作し、必要な HTTP 応答ヘッダーが送信され、続いて、動作を証明するために現在 2 秒または 3 秒ごとに生成しているイベントのストリームが送信されます。
FireFox、Chrome、Opera の最新バージョンを試してみましたが、EventSource オブジェクトを作成して nodejs サーバーに接続できましたが、onopen、onmessage、onerror などのイベントを生成するブラウザはありません。
ただし、nodejsサーバーを停止してブラウザからの接続を終了すると、すべてのメッセージが突然ディスパッチされ、すべてのイベントが表示されます。その後、ブラウザーはすべて、仕様に従ってサーバーへの再接続を試みます。
私はすべてをウェブサーバーでホストしています。ローカル ファイルでは何も実行されていません。
購入した本を含め、オンラインで見つけられるものはすべて読みましたが、そのような問題は何もありません。何か足りないものはありますか?
サンプル サーバーの実装
var http = require('http');
var requests = [];
var server = http.Server(function(req, res) {
var clientIP = req.socket.remoteAddress;
var clientPort = req.socket.remotePort;
res.on('close', function() {
console.log("client " + clientIP + ":" + clientPort + " died");
for(var i=requests.length -1; i>=0; i--) {
if ((requests[i].ip == clientIP) && (requests[i].port == clientPort)) {
requests.splice(i, 1);
}
}
});
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Access-Control-Allow-Origin': '*',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'});
requests.push({ip:clientIP, port:clientPort, res:res});
res.write(": connected.\n\n");
});
server.listen(8080);
setInterval(function test() {
broadcast('poll', "test message");
}, 2000);
function broadcast(rtype, msg) {
var lines = msg.split("\n");
for(var i=requests.length -1; i>=0; i--) {
requests[i].res.write("event: " + rtype + "\n");
for(var j=0; j<lines.length; j++) {
if (lines[j]) {
requests[i].res.write("data: " + lines[j] + "\n");
}
}
requests[i].res.write("\n");
}
}
サンプルの html ページ
<!DOCTYPE html>
<html>
<head>
<title>SSE Test</title>
<meta charset="utf-8" />
<script language="JavaScript">
function init() {
if(typeof(EventSource)!=="undefined") {
var log = document.getElementById('log');
if (log) {
log.innerHTML = "EventSource() testing begins..<br>";
}
var svrEvents = new EventSource('/sse');
svrEvents.onopen = function() {
connectionOpen(true);
}
svrEvents.onerror = function() {
connectionOpen(false);
}
svrEvents.addEventListener('poll', displayPoll, false); // display multi choice and send back answer
svrEvents.onmessage = function(event) {
var log = document.getElementById('log');
if (log) {
log.innerHTML += 'message: ' + event.data + "<br>";
}
// absorb any other messages
}
} else {
var log = document.getElementById('log');
if (log) {
log.innerHTML = "EventSource() not supported<br>";
}
}
}
function connectionOpen(status) {
var log = document.getElementById('log');
if (log) {
log.innerHTML += 'connected: ' + status + "<br>";
}
}
function displayPoll(event) {
var html = event.data;
var log = document.getElementById('log');
if (log) {
log.innerHTML += 'poll: ' + html + "<br>";
}
}
</script>
</head>
<body onLoad="init()">
<div id="log">testing...</div>
</body>
</html>
これらの例は基本的なものですが、本やオンラインで見た他のすべてのデモと同じ種類のものです。eventSource は、クライアント接続を終了するかサーバーを終了する場合にのみ機能しているように見えますが、これは SSE ではなくポーリングであり、特に SSE を使用したいと考えています。
興味深いことに、html5rock のthouseなどのデモも、オンラインで使用すると期待どおりに動作しないようです..