LoginSignup
2
1

More than 1 year has passed since last update.

ServerからWeb Client通信手段としてのServer Sent Events触ってみる

Posted at

なぜ記載したか?

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を利用する手間が省けたり色々と拡張できそうな機能ではあるかなと思います。

スクリーンショット 2023-03-03 13.45.47.png

スクリーンショット 2023-03-03 13.47.15.png

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1