sseSource.ts 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import { EventSourcePolyfill } from "event-source-polyfill";
  2. class SseSource {
  3. private readonly accessId: number
  4. private readonly url: URL
  5. private eventSource: EventSource | null = null
  6. constructor(mercureBaseUrl: string, accessId: number) {
  7. this.accessId = accessId
  8. this.url = new URL(mercureBaseUrl)
  9. this.url.searchParams.append('topic', "access/" + this.accessId)
  10. }
  11. getUrl () {
  12. return this.url
  13. }
  14. isOpen () {
  15. return this.eventSource !== null && this.eventSource.readyState === EventSource.OPEN
  16. }
  17. public subscribe () {
  18. if (this.isOpen()) {
  19. throw new Error('SSE - Already subscribed to this event source')
  20. }
  21. if (process.server) {
  22. throw new Error('SSE - Cannot subscribe on server side')
  23. }
  24. this.eventSource = new EventSourcePolyfill(
  25. this.url.toString(),
  26. { withCredentials: true }
  27. );
  28. this.eventSource.onerror = (event) => {
  29. console.error('SSE - An error happened : ' + JSON.stringify(event))
  30. this.eventSource?.close()
  31. }
  32. this.eventSource.onopen = () => {
  33. console.log('SSE - Listening for events...')
  34. }
  35. this.eventSource.onmessage = event => {
  36. const data = JSON.parse(event.data)
  37. console.log(data)
  38. }
  39. }
  40. public unsubscribe () {
  41. if (this.eventSource === null || this.eventSource.readyState === EventSource.CLOSED) {
  42. return
  43. }
  44. this.eventSource.close()
  45. console.log('SSE - Subscription closed')
  46. }
  47. }
  48. export default SseSource