Observed "retryWhen" delay

How to set delay in retryWhen ?

 import 'rxjs/add/operator/retry'; import 'rxjs/add/operator/retrywhen'; 

...

 constructor(http: Http) { var headers = new Headers(); headers.append('Content-Type', 'text/plain'); http.post('https://mywebsite.azurewebsites.net/account/getip', "", { headers: headers }) .retryWhen(errors => { return errors.delay(1000); // errors is not a function }) (event) => { // handle events this.ip = event.json(); }, (error) => { console.error(error); toastr.error('No connection to server. Please reload the page!') } ); } 

I get an error: errors is not a function .

+6
source share
2 answers
 import {Http, Headers, Response} from '@angular/http'; http.get('http://jsonplaceholder.typicode.com/posts/1/commentsss') .retryWhen(e => e.scan<number>((errorCount, err) => { if (errorCount >= 10) { throw err; } return errorCount + 1; }, 0).delay(1000)) .subscribe(r => console.log(`Sub: ${r}`)) 

Repeats 10 times with a delay of 1 second.

plnkr

+7
source

A little late, but here's how to do it with the new version of rxjs (> 6) I suppose you are trying to automatically retry the network in the event of a failure. This can be achieved in different ways, but here is a very small implementation of RetryWhen () - this operator catches if any errors are generated by the observable, and creates an errorObservable from this. Now, using errorObservable, we can retry for a specified number of attempts for a specific set of errors

For example, retries in the event of a 404 failure are not really needed, but in the case of 500X exceptions, this is really necessary.

DelayWhen - we could use this statement to indicate a timer , observable, which delays the next retry attempt until the time runs out . This also provides the added benefit of linearly increasing the delay between each retry attempt.

iif - using this conditional operator really allows us to filter and execute the necessary observables based on a given condition. You could also give examples in stackoverflow. But I'm going to give a simple illustration, if still

contactMap is a higher-order observable operator, that is, it produces / maps the input / observable to the output of the observable. The reason for using this is that we need to repeat the retry operation in the case of the same failure for the specified number of times, and the best way to restart the operation is through an Observable error. Note that we could use other higher order observable operators, such as mergeMap / switchMap-, each of which has its advantages and disadvantages, but I prefer to use this. Again, ContactMap is different than Concat, so be careful

I believe the best place to implement such a retry in Angular is inside httpinterceptors, but it can also be done inside a service

Here is an example implementation:

 // Class to intercept all network calls and retry for X number of times export class ErrorInterceptor implements HttpInterceptor { // private authService: UserAuthenticationService; private ngxLogger: NGXLogger; private errorHandlerService: ErrorHandlerService; constructor(injector: Injector) { this.ngxLogger = injector.get(NGXLogger); this.errorHandlerService = injector.get(ErrorHandlerService); } intercept( req: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> { const interceptObs$ = next.handle(req); // you could filter for the URLS that this should be applied like this if (req.url.match(API_FETCH_TOKEN)) { let retryAttempts = 0; const httpInterceptor$ = interceptObs$.pipe( retryWhen(errorObs => { return errorObs.pipe( tap(errval => console.log('Retrying because of err:${errval}')), concatMap(errObsValue => { if ( errObsValue instanceof HttpErrorResponse && errObsValue.status != 404 ) { console.log('inside concatMap', errObsValue); if (retryAttempts > APP_NET_RETRIES) { return throwError(this.getErrorModel(errObsValue, req)); } else { retryAttempts++; // this linearly increases the delay of attempts delayWhen(() => timer(retryAttempts * APP_NET_RETRIES_DELAY * 1000) ); return httpInterceptor$; } } }) ); }) ); return httpInterceptor$; } else { return interceptObs$; } // above is the notifier observable, with errors captured as input observable // so we could operate on this observable for retires // also make sure to return the error observable - ie the notifier observable // reason being all errors should again be returned so as to capture them and // only when they are returned they can be retried // Also make sure after take() - no.of retries we just throw a last occuring error obs } // I like to create a custom error model and handle that in Custom ErrorHandler // Below is the sample implementation I use. but again this is your preference // you can just rethrow the error alone async getErrorModel(errValue, req): Promise<ErrorModel> { const errModel = new ErrorModel(); errModel.Error = errValue; errModel.ErrorMessage = 'Error in retrieving the token:' + errValue.message; errModel.ErrorStatus = 421; errModel.ErrorUrl = req.url; errModel.Timestamp = momentTimeZone .tz(DEFAULT_TIME_ZONE) .format(DEFAULT_TIME_ZONE); await this.errorHandlerService.handleError(errModel); return Promise.resolve(errModel); } } 

Hope this helps ..

UPDATE: There is a really good article on backoff-rxjs that really cuts down on everything we did above. Please refer to this link.

+2
source

All Articles