Skip to content

Commit 6f9b16b

Browse files
authored
docs(ngrx): add example of using sse with angular (#20)
1 parent a662114 commit 6f9b16b

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
title: Wrap Server Sent Events (SSE) in Component Store
3+
description: "Set up an SSE listener and store the values in ComponentStore"
4+
tags: ["angular", "ngrx", "state", "sse"]
5+
pubDate: Feb 25, 2023
6+
contributedBy: "@JayCooperBell"
7+
---
8+
9+
Demo of using Server-Sent Events (SSE) with Angular
10+
11+
An SSE is sent every second with the current time to the Angular app that has a persistent EventSource connection to the server.
12+
A NgRx ComponentStore sets up a connection that updates the store with the time from the server.
13+
14+
This example assumes you have an API setup that sends SSE. For a full stack example see https://github.com/yharaskrik/nest-ng-ngrx-component-store-sse-demo
15+
16+
Set up a global NgRx Store with Effects.
17+
```typescript
18+
import { Injectable, NgZone } from '@angular/core';
19+
import { ComponentStore, tapResponse } from '@ngrx/component-store';
20+
import { Observable, Subject } from 'rxjs';
21+
22+
function eventSourceToObservable(
23+
source: string,
24+
_ngZone: NgZone
25+
): Observable<{ now: string }> {
26+
/*
27+
* Set up a Subject we will use as a pass through for the EventSource that is listening to SSE to emit
28+
* to the NgRx ComponentStore effect
29+
*/
30+
const passThrough = new Subject<{ now: string }>();
31+
32+
/*
33+
* The EventSource that opens a persistent connection to the server to listen for Server Sent Events (Sse)
34+
*/
35+
const eventSource = new EventSource(`/api/${source}`);
36+
37+
eventSource.onmessage = (e) =>
38+
/*
39+
* Need to run the `passThrough.next` inside of Zone so that Angular knows it has occurred and can make sure that the
40+
* UI is updated.
41+
*
42+
* Reference: https://blog.octo.com/en/angular-2-sse-and-changes-detection/
43+
*/
44+
_ngZone.run(() => passThrough.next(JSON.parse(e.data)));
45+
46+
return passThrough;
47+
}
48+
49+
export interface TimeSseState {
50+
now: string;
51+
}
52+
53+
@Injectable()
54+
export class TimeSseStore extends ComponentStore<TimeSseState> {
55+
readonly now$ = this.select((state) => state.now);
56+
57+
readonly setNow = this.updater((state, now: string) => ({ ...state, now }));
58+
59+
constructor(private _ngZone: NgZone) {
60+
super({ now: new Date().toISOString() });
61+
}
62+
63+
/*
64+
* An NgRx ComponentStore effect that will listen on our PassThrough EventSource and update the state with the
65+
* date sent from the server.
66+
*/
67+
readonly getTime$ = this.effect(() =>
68+
eventSourceToObservable('time', this._ngZone).pipe(
69+
tapResponse(
70+
(data) => {
71+
this.setNow(data.now);
72+
},
73+
(error) => console.error(error)
74+
)
75+
)
76+
);
77+
}
78+
```
79+
80+
References:
81+
1. https://docs.nestjs.com/techniques/server-sent-events
82+
2. https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
83+
3. https://ngrx.io/guide/component-store/effect

0 commit comments

Comments
 (0)