a.oub-c
a.oub-c

Reputation: 65

Retry getting result from backend server if certain condition not met

I'm tring to get results from server, and retry until i get the right results using rxjs.

code snippet:

const intervalSub = interval(timeout).subscribe(t => {
  const userSearchSub2 = this.userSearchService.getSearchResult(searchReq).subscribe(xx => {
    if (xx.results) {
      this.dataSource.data = xx.results.map((item: any) => item.values);
      intervalSub.unsubscribe();
    }

    userSearchSub2.unsubscribe();
  });
});

Since the inerval is faster than 'getSearchResult', getSearchResult executes several times even if i get my results in the first attempts.

wanted behavior:

Stop interval until i check the results of getSearchResult, so getSearchResult do not fire again if i have my results

Upvotes: 1

Views: 161

Answers (1)

Andrei Gătej
Andrei Gătej

Reputation: 11979

This seems to be a good use case for exhaustMap.

You have an outer observable(the interval) and for each emitted value, you would want to make a request, which will create another observable(inner observable), but you do not want to go to the next emission of the interval until the current inner observable completes.

let resultsFound = false;

interval(timeout)
    .pipe(
        takeWhile(() => !resultsFound),
        exhaustMap(() => this.userSearchService.getSearchResult(searchReq)),
        map(xx => {
            if (xx.results) {
                resultsFound = true;

                return xx.results.map((item: any) => item.values);
            }

            return null;
        }),
        filter(v => !!v),
    )
    .subscribe(results => console.log(results))

Your case is similar to http polling. Might be worth checking the provided link out.

When takeWhile's predicate function returns false(() => !resultsFound, resultsFound = true), it will automatically unsubscribe from the outer observalbe.

Upvotes: 2

Related Questions