'Wait until a certain value is true in RXJS

I am using angular and rxjs with an external service :

I have the following method (simplified)

  getElevation(pos: Cesium.Cartographic): Observable<number> {
    if (!this.ready) {
      return throwError("NOT READY");
    }
    return new Observable<number>((observer) => {
        const promise = GetPromise();
        promise.then(
          (value) => {
            observer.next(value);
            observer.complete();
          },
          () => {
            throwError("PROMISE ERROR");
          }
        );
      });
    });
  }

I would like to make that ready an ReplaySubject, and wait for it to be true before doing the promise, OR directly do the operation.

so I made something like this (again simplified to show the logic) :

  private ready$ = new ReplaySubject<any>(1);


  constructor(private ngZone: NgZone, private myService: MuService) {
    this.myService.isElementReady$.subscribe((isReady) => {
        this.ready$.next(isReady);
    });
  }

but I have no idea how to merge the ready$ with my method. like I was doing

  getElevation(pos: Cesium.Cartographic): Observable<number> {
    return this.ready$.pipe(
      switchMap((value) => {
        if(value) {
          return from(GetPromise())
          ).pipe(
            switchMap((value) => of(updatedPositions[0].height))
          );
        } else {
          // wait for ready 
        }
      })
    );

READY can become false when some value are reset in the service, so this thing must always be checked



Solution 1:[1]

You can use first if you want the code to execute only once.

getElevation(pos: Cesium.Cartographic): Observable<number> {
  return this.ready$.pipe(
    first(v => v), // This will take only the first 'true' value
    switchMap((value) => {
      return from(GetPromise())
        .pipe(
          switchMap((value) => of(updatedPositions[0].height))
        );
    })
  );

Or use filter if you want it to run every time a value matching the filter is emitted.

getElevation(pos: Cesium.Cartographic): Observable<number> {
  return this.ready$.pipe(
    filter(v => v), // This will take all 'true' value and ignore the rest
    switchMap((value) => {
      return from(GetPromise())
        .pipe(
          switchMap((value) => of(updatedPositions[0].height))
        );
    })
  );

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1