Angular Rxjs使用延迟函数重试
我正在尝试使用Angular Rxjs使用延迟函数重试,angular,typescript,rxjs,Angular,Typescript,Rxjs,我正在尝试使用retry和delay函数,我希望函数会在1000毫秒延迟后调用,但它没有,这里会有什么错误? 请看控制台输出,时间是16:22:48 我希望那里是16:22:48,16:22:59 canCreate: boolean; getSomeFunction(): Observable<boolean> { return new Observable<boolean>( observer => {
retry
和delay
函数,我希望函数会在1000毫秒延迟后调用,但它没有,这里会有什么错误?
请看控制台输出,时间是16:22:48
我希望那里是16:22:48,16:22:59
canCreate: boolean;
getSomeFunction(): Observable<boolean> {
return new Observable<boolean>(
observer => {
const canCreate = null; // this is just null for now, will some value later
if (canCreate == null) {
observer.error('error');
} else {
observer.next(true);
}
observer.complete();
}
)
}
this.getSomeFunction()
.do((value) => {
this.cCreate = value;
}, (error) => {
console.log(error + new Date().toTimeString());
})
.delay(1000)
.retry(10)
.subscribe(
value => this.cCreate = value,
error => {
this.cCreate = false;
},
() => {}
);
}
canCreate:boolean;
getSomeFunction():可观察{
返回新的可观测数据(
观察员=>{
const canCreate=null;//现在这只是null,以后会有一些值吗
if(canCreate==null){
观察者错误(“错误”);
}否则{
观察者:下一个(正确);
}
observer.complete();
}
)
}
this.getSomeFunction()
.do((值)=>{
this.cCreate=值;
},(错误)=>{
log(错误+新日期().toTimeString());
})
.延迟(1000)
.重试(10)
.订阅(
value=>this.cCreate=value,
错误=>{
this.cCreate=false;
},
() => {}
);
}
结果是:
这可能会对您有所帮助
let values$ = Rx.Observable.interval(1000).take(5);
let errorFixed = false;
values$
.map((val) => {
if(errorFixed) { return val; }
else if( val > 0 && val % 2 === 0) {
errorFixed = true;
throw { error : 'error' };
} else {
return val;
}
})
.retryWhen((err) => {
console.log('retrying again');
return err.delay(1000).take(3); // 3 times
})
.subscribe((val) => { console.log('value',val) });
用于在可观察对象发出的事件之间引入延迟。但可观测的物体从来不会发出任何事件。它只是立即出错
您需要的是,它允许您在重试多长时间后决定:
RxJS 5:
.retryWhen(errors => errors.delay(1000).take(10))
.retryWhen(errors => errors.delay(1000).take(10).concat(Observable.throw()))
RxJS 6:
import { retryWhen, delay, take } from 'rxjs/operators'
someFunction().pipe(
// ...
retryWhen(errors => errors.pipe(delay(1000), take(10)))
)
import { retryWhen, delay, take, concatMap, throwError } from 'rxjs/operators'
someFunction().pipe(
// ...
retryWhen(errors => errors.pipe(delay(1000), take(10), concatMap(throwError)))
)
这将在10次尝试后完成整个观察。如果要在10次尝试后对整个可观察对象出错,retryWhen回调返回的可观察对象必须抛出:
RxJS 5:
.retryWhen(errors => errors.delay(1000).take(10))
.retryWhen(errors => errors.delay(1000).take(10).concat(Observable.throw()))
RxJS 6:
import { retryWhen, delay, take } from 'rxjs/operators'
someFunction().pipe(
// ...
retryWhen(errors => errors.pipe(delay(1000), take(10)))
)
import { retryWhen, delay, take, concatMap, throwError } from 'rxjs/operators'
someFunction().pipe(
// ...
retryWhen(errors => errors.pipe(delay(1000), take(10), concatMap(throwError)))
)
我使用
retryWhen
和Observable.Interval
提出了以下解决方案,但在这个解决方案中,error
subscribe-never函数调用
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());
}
);
添加到@JB Nizet的答案中。如果您是在rxjs 5+中使用lettable操作符编写的,请将其结构为
retryWhen(errors=>errors.pipe(延迟(1000),取(5))
对于ngrx5+我们可以创建操作符:
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);
})
))
);
}
适用于rxjs版本6.3.3
打开控制台并查看重试
示例代码
RxJS提供了
retry
操作符,当出现错误时,该操作符将重新订阅给定计数次数的可观测值。在抛出错误之前,retry
操作符会针对给定的计数次数重新订阅可观测错误,如果仍然存在错误,则抛出错误<代码>重试对于多次点击URL很有用。由于网络带宽的原因,URL可能不会一次性返回成功的数据,而当它重新定时时,可能会成功返回数据。如果重试后,Observable中仍然存在错误,则可以使用catchError
返回带有用户定义的默认数据的Observable
getBook(id:number):可观察{
返回此.http.get(this.bookUrl+“/”+id).pipe(
重试(3),
catchError(err=>{
控制台日志(err);
返回(空);
})
);
}
我最近遇到了这个问题,并发现可接受的解决方案可以改进
Observable.pipe(
retryWhen(errors => errors.pipe(
delay(1000),
take(10))),
first(v => true),
timeout(10000))
它的基本功能是如前所述重试,但这会立即结束,而不会使用“first”运算符添加任何(错误的)值
如果在超时时间范围内找不到值,则会引发错误。所有这些都是RxJS 6+
TL;博士 您可以使用此软件包中经过充分测试的运算符,或向下滚动查看源代码:)
标准 由于其他答案中的大多数(或者可能没有一个)不符合我的所有标准,我将在下面列出我的解决方案。目标:
- 如果没有抛出错误,则定期发出并完成。✅李>
- 如果抛出错误,则重试
次。✅李>x
- 每次重试前的延迟为
。✅李>y
- 返回上次发出的错误。(许多其他答案都在努力解决这个问题。)✅李>
- 用
正确输入–但这很难搞糟。✅李>strict:true
解决方案 与其他答案一样,我们将使用操作符捕捉错误。要跟踪重复次数,可以使用运算符。为了限制重复次数,我们只需在操作符中抛出一个错误 原始源代码使用,但在这种情况下,我们可以简单地使用from 最后,我们将使用运算符添加不同执行之间的延迟:
import { MonoTypeOperatorFunction } from 'rxjs';
import { delay as delayOperator, map, retryWhen, scan } from 'rxjs/operators';
export function retryWithDelay<T>(
delay: number,
count = 1
): MonoTypeOperatorFunction<T> {
return (input) =>
input.pipe(
retryWhen((errors) =>
errors.pipe(
scan((acc, error) => ({ count: acc.count + 1, error }), {
count: 0,
error: undefined as any,
}),
map((current) => {
if (current.count > count) {
throw current.error;
}
return current;
}),
delayOperator(delay)
)
)
);
}
从'rxjs'导入{monotypetoperatorfunction};
从'rxjs/operators'导入{delay as delayOperator,map,retryWhen,scan};
导出函数retryWithDelay(
延迟:数字,
计数=1
):单类型运算符函数{
返回(输入)=>
输入管道(
retryWhen((错误)=>
水管(
扫描((acc,error)=>({count:acc.count+1,error}){
计数:0,
错误:未定义为任何,
}),
地图((当前)=>{
如果(current.count>count){
抛出电流误差;
}
回流;
}),
delayOperator(延迟)
)
)
);
}
来源
- –可能会派上用场
import {delay as _delay, map, retryWhen} from 'rxjs/operators';
export const delayedRetry = (delay, retries = 1) => retryWhen(result => {
let _retries = 0;
return result.pipe(
_delay(delay),
map(error => {
if (_retries++ === retries) {
throw error;
}
return error;
}),
);
},
);
用法
错误的类型是可观察的
,它没有完整的
方法我误解了文档。现在应该没事了。请看,我得到的是“提供的参数与调用目标的任何签名都不匹配。关于Observable.throw()”,因此“Observable.throw('error')对我有效,非常感谢您的回答。这对我无效。我一直得到属性“concat”在类型“Observable”上不存在。
即使我导入了concat,import”rxjs/add/observable/concat”
!以下是较新Angular/rxjs版本的完整代码:pipe(retryWhen(error=>error.pipe(delay(1000)、take(3)、concat(Obser