I have a service that looks like this:
export class WebViewService {
private webViewMessage = new ReplaySubject<any>(1);
public webViewMessage$ = this.webViewMessage.asObservable();
public isWebView: boolean = false;
constructor() {
this.isWebView = false;
if (window?.chrome?.webview)
{
this.isWebView = true;
}
window?.chrome?.webview?.addEventListener('message', (event: { data: any; }) => {
this.webViewMessage.next(event.data);
});
}
public postMessage(message: any) {
window?.chrome?.webview?.postMessage(message);
}
}
And I have a component that looks like this:
export class BrowserComponent implements OnInit {
constructor(private webViewService: WebViewService) { }
subscription!: Subscription;
ngOnInit(): void {
this.subscription = this.webViewService.webViewMessage$.subscribe(o => {
alert(o);
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
onClick() {
this.webViewService.postMessage("showDialog");
}
}
When the onClick() method is called, a message is posted via the webViewService which in turn results in the parent window (a windows form) showing a file dialog and then I want to know what the response is, and that will be in the webViewMessage$. I am showing an alert() now in the subscription but in future, it'll be different.
Problem: when I leave the Browse component and then enter it again, the alert pops up with the last webViewMessage$, which is what I would expect but not what I want.
I can change the onClick() code to something like this:
onClick() {
this.webViewService.postMessage("showDialog");
this.subscription = this.webViewService.webViewMessage$.subscribe(o => {
alert(o);
this.subscription.unsubscribe();
});
}
However, this pops up a the last message as soon as I click the onClick() button again - I know why this happens, but I have no way to "wait" for postMessage() method to receive a response. But again, I only want the message that has been received AFTER this.webViewService.postMessage() has been called. How would I do this??
CodePudding user response:
A BehaviorSubject
is made to retain the last value emitted. That's why when you create it, you have to provide a default value.
A ReplaySubject
is made to retain a given number of values emitted. When creating it, you must specify how many values you wish to retain.
Instead, use a Subject
, which observers will trigger only when a value is sent through, and that does not retain the last value emitted.
private webViewMessage = new Subject<any>();