I am using SSE events in my application. For that I have written code which works just fine.
Problem I am facing is I need to close connection after certain time manually let say on some user action. I am not getting any option to do so.
eventSource.close() is there but its in service and unsubscribing it in component doesn't work.
Here goes my code:
***** service.ts*****
public getServerSentEventsForTokenDisplay(url: string): Observable<any> {
return Observable.create(observer => {
const eventSource: EventSourcePolyfill = this.getEventSource(url);
eventSource.addEventListener('XXX', (event: any) => {
observer.next(event);
});
eventSource.addEventListener('YYY', (event: any) => {
observer.next(event);
});
eventSource.addEventListener('Ack', (event: any) => {
observer.next(event);
});
eventSource.onerror = (error) => {
eventSource.close()
this.ngZone.run(() => observer.next(error));
};
eventSource.onopen = (event) => {
this.ngZone.run(() => observer.next(event));
};
});
}
**** component.ts ***** `
private getTokenDisplay(url) {
let url = url;
this.isWaitingTokensLoading = true;
this.isTokenDisplayLoading = true;
this.tokenDisplaySubscription = this.qmsService.getServerSentEventsForTokenDisplay(url).pipe(takeUntil(this.ngUnsubscribe)).subscribe((response: MessageEvent) => {
if (response && response.type === 'open') {
console.log(response)
}
if (response && response.type.toLowerCase() === 'ack') {
console.log(response)
}
if (response && response.type === 'XXX') {JSON.parse(response.data));
let parsedData = JSON.parse(response.data);
this.tokenDisplayList = parsedData.data;
this.isTokenDisplayLoading = false;
}
if (response && response.type === 'YYY') {
let parsedData = JSON.parse(response.data);
this.waitingTokens = parsedData.data;
this.isWaitingTokensLoading = false;
}
if (response && response.type === 'error') {
console.log(response);
}
}, (error) => {
this.isWaitingTokensLoading = false;
this.isTokenDisplayLoading = false;
console.log(error)
})
}
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.unsubscribe();
if(this.tokenDisplaySubscription)
this.tokenDisplaySubscription.unsubscribe();
}`
I need to close SSE connection manually.
CodePudding user response:
You can start by not using the deprecated Observable.create
method anymore, but the Observable
constructor itself. The recommended way to dispose of the resources that are used by an observable whenever they are not needed anymore (the observable has no more subscribers) is to return a function in which you can clean up. Something like this:
return new Observable(observer => {
const eventSource: EventSourcePolyfill = this.getEventSource(url);
eventSource.addEventListener('Token-Display', (event: any) => {
observer.next(event);
});
eventSource.addEventListener('Token-Waiting', (event: any) => {
observer.next(event);
});
eventSource.addEventListener('Ack', (event: any) => {
observer.next(event);
});
eventSource.onerror = (error) => {
eventSource.close()
this.ngZone.run(() => observer.next(error));
};
eventSource.onopen = (event) => {
this.ngZone.run(() => observer.next(event));
};
return () => {
console.log('Closing event source...');
eventSource.close();
}
});