- setIntervalで定期的にevnetを送るのと、redisのPub/Subを利用してeventを送るのという2種類。
- イベント発生時にレスポンスを書き出すようにするのは、EventEmitterを経由する。
- resdisからeventを送るのを試すにはredis-cliを使って、'redis-cli publish node-sse-example:myevent foo'みたいにすればいい。
- クライアントサイドのコードのも一緒に書いているけど、簡単に実行できるように1ファイルにしたかったからで、普通は分ける方がいい。
- nginxでreverse proxyしたときのバッファリングをオフにするためにX-Accel-Bufferingヘッダーをつけている。
- バッファリングに気をつければnginx経由でも簡単に動くので、そこはwebsocketよりだいぶ楽。
var util = require('util')
var events = require('events')
var express = require('express')
var redis = require('redis')
var app = express.createServer()
var notifyEmitter = new events.EventEmitter()
var redisClientSubscriber = redis.createClient()
redisClientSubscriber.on('message', function(ch, d) {
util.log(JSON.stringify(['redisSubscriber', ch, d]))
notifyEmitter.emit('myevent', 'redis node-sse-example:myevent ' + d)
})
redisClientSubscriber.subscribe('node-sse-example:myevent')
setInterval(function() {
var len = notifyEmitter.listeners('myevent').length
util.log(JSON.stringify(['listeners.length', len]))
if (len > 0) {
notifyEmitter.emit('myevent', 'interval!')
util.log(JSON.stringify(['emit myevent']))
}
}, 10 * 1000)
app.get('/', function(req, res) {
var r = '<html><head><script>\n'
var f = function() {
var es = new EventSource('/sse')
es.onmessage = function(m) {
document.body.innerHTML += m.data + new Date() + '<br />'
}
es.onerror = function(e) {
console.log('err:', e)
}
}
r += 'var f = ' + f.toString() + '\n' + 'f()'
r += '\n</script></head><body><h1>sever sent events test</h1></body></html>'
res.send(r)
})
app.get('/sse', function(req, res) {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'X-Accel-Buffering': 'no' // disable nginx proxy buffering
})
res.write('\n')
var f = function(d) {
res.write('data: ' + d + ' \n\n')
}
notifyEmitter.on('myevent', f)
req.on('close', function() {
notifyEmitter.removeListener('myevent', f)
})
})
app.listen(9301)
console.log('see http://localhost:9301/')
console.log("publish by redis 'redis-cli publish node-sse-example:myevent foo'\n")
https://gist.github.com/2823050