Using HttpClient to create EventStream request

Viewed 420

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

1 Answers

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)));
        });
    }
Related