4

I used the following code to get an event stream from server:

getStream(): Observable<ResponseModel> {
    return new Observable(obs => {
      const source = new EventSource(`http://backend/api/stream`);
      source.onmessage = (ev): void => this.zone.run(() => obs.next(JSON.parse(ev.data)));
      source.onerror = (err): void => this.zone.run(() => obs.error(err));
    });
}

...which works as expected. But now I need to treat the EventStream the same way other HTTP requests are being treated - which I do with interceptors. Interceptors do not work with EventSource.

So I tried something like this instead:

constructor(
  private http: HttpClient,
  private zone: NgZone
) {}


getStream(): Observable<ResponseModel> {
    return new Observable(obs => {
        const req = new HttpRequest('GET', `http://backend/api/stream`, {
          observe: 'body',
          headers: new HttpHeaders({
            Accept: 'text/event-stream',
            'Cache-Control': 'no-cache'
          })
        });
        const source = this.http.request<ResponseModel>(req).subscribe(ev => this.zone.run(() => obs.next(ev)));
    });
}

What seems to be the right direction, as the request stays pending on Chrome's network tab until something is fired (although, data is empty):

enter image description here

So, how would I do that?

Thanks

noamyg
  • 2,747
  • 1
  • 23
  • 44
  • Have you tried this answer: https://stackoverflow.com/questions/36812714/using-rxjs-and-angular-2-in-order-to-deal-with-server-sent-events It would appear Typescript has an EventSource object which you could convert to an observable. From the looks of it I have to wonder if it couldnt even be combined with a HostListener – Vinez Jan 06 '22 at 12:26
  • @Vinez the accepted answer of that question is basically a "no" answer to my question. I'm looking for a way to apply interceptors on EventSource, not just to "make it work". – noamyg Jan 07 '22 at 07:43

1 Answers1

1

rather than an interceptor could you make a common method all event streams are initiated from and apply whatever pipes you want to that?

    createStream(verb, url): Observable<ResponseModel> {
          
        return new Observable(obs => {
            const req = new HttpRequest(verb, url, {
              observe: 'body',
              headers: new HttpHeaders({
                Accept: 'text/event-stream',
                'Cache-Control': 'no-cache'
              })
            }).pipe(
startWithTap(() => //do my pre request stuff here),
tap(() => // do my post request stuff here));
            const source = this.http.request<ResponseModel>(req).subscribe(ev => this.zone.run(() => obs.next(ev)));
        });
    }
Vinez
  • 560
  • 2
  • 11