RXJS Repeat query until a condition is met?

筅森魡賤 提交于 2020-08-27 08:55:12

问题


I'm using an API that returns only a limited number of results, say 100.

I'd like to repeat a query until the return result set is < 100 which would mean I've got the last result.

So it would go like this:

  1. Make query
  2. Is result set less than limit? If so, do again and append results.
  3. Once result set is less than limit, emit the final result.

回答1:


You can use the expand operator for a simple "conditional repeat" behavior.

Just for the example, instead of a result set I changed the query to return a number. The following keep querying until the retrieved number is less than 100

const { defer, empty } = rxjs;
const { expand, toArray} = rxjs.operators;

const query$ = defer(async () =>  Math.floor(Math.random()*1000));
   
query$
  .pipe(
    expand(result => result < 100 ? empty() : query$),
    toArray()
  )
  .subscribe(console.log);
<script src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"></script>



回答2:


You can also use RXJS Interval with TakeWhile operator. Here is the sample code

In Component:

return Observable
  .interval(250)
  .flatMap(() => this.getQueryData())
  .takeWhile(data => this.checklimit(data))
  .subscribe(result => console.log(result);

getQueryData(){
   // HTTTP API call 
}

checklimit(){
  // return true/false
}



回答3:


 stop$: Subject = new Subject();

 query$.pipe(takeUntil(this.stop$)).subscribe( result => {
    if(result < limit) 
       this.stop$.next();
       this.stop$.complete();
     }
   else {
      process result, i.e append somewhere...
   }
 });

Note his is the RxJs 6 syntax. For readability you can extract the subscribe logic in a method.

Maybe working with takeWhile is easier in this case:

doQuery: boolean = true;

 query$.pipe(takeWhile(()=> this.doQuery).subscribe( result => {
    if(result < limit) 
       this.doQuery = false;
     }
   else {
      process result, i.e append somewhere...
   }
 });



回答4:


We can also use the repeatWhen operator (which is similar to retryWhen but works on complete instead of on error):

this.queryData().pipe(
    repeatWhen(obs => obs),
    filter(data => this.checkLimit()),
    take(1)
).subscribe(result => console.log(result));

Note: the take(1) is needed to stop the repeatWhen loop.

If we need a delay between retries, we can do:

repeatWhen(obs => obs.pipe(delay(1000)))


来源:https://stackoverflow.com/questions/51640489/rxjs-repeat-query-until-a-condition-is-met

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!