问题
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:
- Make query
- Is result set less than limit? If so, do again and append results.
- 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