なぜ記載したか?
serverからweb clientの通信手段を遊びで実装しようとおもった際に、結構脳死でwsプロトコルを利用していたが、改めてかるく調べてみようと思い調べてみたら複数の手段があった。
その手段の中でも、wsプロトコルに依存せずにwsプロトコルに似た挙動をした通信手段があったため軽く試してみた結果を記載
注意
Firefoxにはまだ対応していない(2023.3.15現在)いません。
Firefox
mdn
0. 利用環境
dependency | version |
---|---|
react | 18.0.27 |
nextjs | 9.0.0 |
環境作成
APIを作成
nestjsについては、Server-sent Eventがdefaultでsupportされているため、そのまま利用する。
ref
app.controller.ts
import { Controller, Get, MessageEvent, Sse } from '@nestjs/common';
import { Observable, interval, map } from 'rxjs';
@Controller()
export class AppController {
@Sse('sse')
sse(): Observable<MessageEvent> {
return interval(1000).pipe(map((_) => ({ data: { hello: 'world' } })));
}
}
新しいpackageを追加せずにdefaultで利用が可能になっているため、素敵すぎます。
上記の設定で、http://localhost:3000/sseに接続を実施すれば、ServerSentEventの確認が取れます。
web clientの実装
あくまで、http + web workerの機能になるのであまり新しいことはないですが、Reactだとこんな感じになるかなと(雑)。
App.tsx
import { useEffect } from 'react'
import './App.css'
import { useEventSource } from './useEventSource'
function App() {
const { connectToEventSource, closeEventSource } = useEventSource()
useEffect(() => {
connectToEventSource("http://localhost:3000/sse")
return () => {
closeEventSource()
}
}, [])
return (
<div className="App">
<div>smaple</div>
</div>
)
}
export default App
useEventSource.tsx
import { useCallback, useRef } from "react"
export function useEventSource() {
const eventSourceRef = useRef<EventSource | null>(null)
const connectToEventSource = useCallback((eventSourceUrl: string, onMessage?: () => void) => {
if (eventSourceRef.current === null) {
const eventSource = new EventSource(eventSourceUrl)
eventSource.onmessage = function (msg) {
const data = JSON.parse(msg.data)
console.log(msg, data)
}
eventSource.onerror = function (msg) {
console.log(msg)
}
eventSourceRef.current = eventSource
return
}
}, [])
const closeEventSource = useCallback(() => {
if(eventSourceRef.current !== null) {
eventSourceRef.current.close()
eventSourceRef.current = null
}
}, [eventSourceRef.current])
return {
closeEventSource,
connectToEventSource
}
}
local で起動実施を確認すると以下のようなデータの取得ができます。
少ししかさわっていませんが、通知周りでwssを利用する手間が省けたり色々と拡張できそうな機能ではあるかなと思います。