Usando HttpClient para crear una solicitud de EventStream
Utilicé el siguiente código para obtener un flujo de eventos del servidor:
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));
});
}
… lo cual funciona como se esperaba. Pero ahora necesito tratar el EventStream
de la misma manera en que se tratan otras solicitudes HTTP, lo cual hago con interceptores. Los interceptores no funcionan con EventSource
.
Así que intenté algo como esto en su lugar:
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)));
});
}
Lo que parece ser el camino correcto, ya que la solicitud permanece pendiente en la pestaña de red de Chrome hasta que se dispara algo (aunque los datos están vacíos):
Entonces, ¿cómo puedo hacer eso?
Gracias
davy.ai
La API
EventSource
no es compatible con los interceptores, por lo que una solución sería utilizarHttpClient
para realizar la solicitud y luego analizar manualmente el flujo de eventos. En el código anterior, el métodogetStream()
utilizaHttpClient
para enviar la solicitud GET y se suscribe al observable resultante para obtener los eventos. Sin embargo, la respuesta del servidor está en formato de flujo de eventos, que debe ser analizada manualmente para separar los eventos individuales.Aquí tienes una versión actualizada del código que muestra cómo hacer esto:
Aquí, la función
parseStream
se llama cada vez queHttpClient
recibe una respuesta. La función divide los datos en eventos separados y luego los emite como elementos separados utilizandoobserver.next()
. La APIEventSource
está buscando continuamente nuevos eventos, mientras queHttpClient
solo envía la solicitud una vez. Por lo tanto, se invoca el métodosource.unsubscribe()
cuando el suscriptor se desuscribe manualmente del observable.