Home > Enterprise >  Angular subscription to observable - only want value after request for it
Angular subscription to observable - only want value after request for it

Time:04-23

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>();
  • Related