I am trying to use retry
with delay
function, I expect function will call after 1000ms delay, but it doesnot, what can be error here?
look at conso
delay() is used to introduce a delay between events emitted by the observable. But the observable never emits any event. It just errors immediately.
What you're looking for is retryWhen(), which allows deciding after how long to retry:
RxJS 5:
.retryWhen(errors => errors.delay(1000).take(10))
RxJS 6:
import { retryWhen, delay, take } from 'rxjs/operators'
someFunction().pipe(
// ...
retryWhen(errors => errors.pipe(delay(1000), take(10)))
)
This will complete the whole observable after 10 attempts. If you want to error the whole observable after 10 attempts, the observable returned by the retryWhen callback must throw:
RxJS 5:
.retryWhen(errors => errors.delay(1000).take(10).concat(Observable.throw()))
RxJS 6:
import { retryWhen, delay, take, concatMap, throwError } from 'rxjs/operators'
someFunction().pipe(
// ...
retryWhen(errors => errors.pipe(delay(1000), take(10), concatMap(throwError)))
)
I come up with following solution using retryWhen
and Observable.Interval
, but in this solution, error
function of subscribe never calls,
this.branchService.getCanCreate()
.do((value) => {
this.cCreate = value;
}, (error) => {
console.log('do', error + new Date().toTimeString());
})
.retryWhen(errors => {
return Observable.interval(1000).take(3).concat(Observable.throw('error')));
})
.subscribe(
value => {
this.cCreate = !!value
console.log('success', new Date().toTimeString());
},
error => {
console.log('subscribe', error + new Date().toTimeString());
this.cCreate = false;
},
() => {
console.log('finally', new Date().toTimeString());
}
);
RxJS provides retry
operator that resubscribes the Observable for the given number of count when there is an error. Before throwing error Observable is resubscribed for the given number of count by retry
operator and if still there is an error, then error is thrown. retry
is useful to hit the URL many times. It is possible that because of network bandwidth, URL does not return successful data in one time and when it reties, it may return data successfully. If after retying still there is error in Observable then catchError
can be used to return Observable with user defined default data.
getBook(id: number): Observable<Book> {
return this.http.get<Book>(this.bookUrl + "/" + id).pipe(
retry(3),
catchError(err => {
console.log(err);
return of(null);
})
);
}
For ngrx5+ we could create operator:
function retryRequest(constructor: () => Observable, count: number, delayTime: number) {
let index = 0;
return of(1) // we need to repeat not the result of constructor(), but the call of constructor() itself
.pipe(
switchMap(constructor),
retryWhen(errors => errors.pipe(
delay(delayTime),
mergeMap(error => {
if (++index > count) {
return throwError(error);
}
return of(error);
})
))
);
}