如何在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!')
}
);
}我得到了错误:errors is not a function。
发布于 2016-09-10 07:15:17
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}`))此操作重试10次,延迟1秒。
plnkr
发布于 2019-10-08 21:12:22
有点晚了,但这是如何处理新版本的rxjs ( >6)我猜您正在尝试在失败的情况下自动重试网络。这可以通过不同的方式来实现,但这里有一个非常小的实现,RetryWhen() - This操作符可以捕获可观察对象抛出的任何错误,并从中创建errorObservable。现在,使用errorObservable,我们可以针对一组特定的失败重试指定的尝试次数
例如,在404失败的情况下重试确实是不必要的,但在500X异常的情况下它确实是强制性的。
DelayWhen -我们可以使用此运算符指定一个timer observable,它会延迟下一次重试尝试,直到该时间过去。这还提供了线性地增加每次重试尝试之间的延迟的附加优势
iif -使用这个条件运算符可以让我们根据给定的条件过滤并执行必要的可观察对象。你也可以在stackoverflow中举例。但我将给出一个简单的if else示例
contactMap -这是高阶可观察运算符,意味着它产生输出可观测对象的输入/可观测对象( /maps )。使用它的原因是,我们需要在相同失败的情况下重试指定次数的重试操作,而重启操作的最佳方法是通过观察到错误。请注意,我们可以使用其他高阶可观察运算符,如mergeMap/switchMap-每个运算符都有自己的优点和缺点,但我更喜欢使用这种方式。同样,contactMap不同于concat运算符,因此这里需要小心
我发现在Angular中实现这样的重试的最佳位置是在httpinterceptors中,但这也可以在服务内部完成。
下面是一个示例实现:
// 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 - i.e 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);
}
}希望这会有帮助..。
编辑:有一篇关于backoff-rxjs的很好的文章,它确实缩短了我们上面所做的一切。请参考this link
发布于 2021-07-28 22:25:35
我找到了这个页面,并做了一些改进:
retryWhen(errors => errors.pipe(
takeWhile((err, index) => {
if (index === 3) throw new Error(err.toString());
return true
}),
delay(1000),
))https://stackoverflow.com/questions/39146958
复制相似问题