Server Sent Events(SSE)をexpressで扱ってみます。
SSEは何かというとだいたいweb socketみたいなものです。
ただ、SSEはサーバからクライアントへの単一方向通信であり、ただのHTTPストリーミングです。
伝統的に、Web ページが新たなデータを受け取るにはサーバにリクエストを送信しなければなりません。すなわち、ページがサーバからデータを要求します。Server-sent events によって、サーバが Web ページにメッセージをプッシュすることにより、サーバから Web ページへ新たなデータをいつでも送信できます。入ってくるメッセージは、Web ページ内のイベントおよびデータとして扱うことができます。
https://developer.mozilla.org/ja/docs/Server-sent_events
使い方は単純で数行で実装できます。クライアントサイドでは、EventSource
を使うだけです。
app.ts
import * as Express from 'express'
const app: Express.Application = Express()
const template = `
<!DOCTYPE html><html><body>
<h1>SSE Express</h1>
<script type="text/javascript">
const source = new EventSource("/events/");
source.onmessage = e => {
console.log(JSON.parse(e.data))
document.body.innerHTML += e.data + "<br>"
};
</script></body></html>`
const { PORT = 3000 } = process.env
let clientId = 0
let clients = {}
app.get('/', (req, res) => {
res.send(template)
})
app.get('/events/', function(req, res) {
req.socket.setTimeout(Number.MAX_VALUE)
res.writeHead(200, {
// text/event-stream を追加
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keep-alive',
})
res.write('\n')
;(clientId => {
clients[clientId] = res
req.on('close', function() {
delete clients[clientId]
})
})(++clientId)
})
setInterval(() => {
const msg = Math.random()
console.log('Clients: ' + Object.keys(clients) + ' <- ' + msg)
for (let clientId in clients) {
// メッセージの送信 \n\nが必要
clients[clientId].write('data: ' + msg + '\n\n')
}
}, 2000)
app.listen(PORT, () => {
console.log(`listing port http://localhost:${PORT}`)
})
2秒ごとにブラウザにデータを送信する簡単なものです。
EdgeやIEでサポートされていないのが難点ですが、リアルタイム通知あたりなどを簡単に実装できるので使いみちはありそうです。