我需要来自数组中每个服务的数据才能在forkjoin调用结束时返回,因此,如果失败了,我需要它再次尝试调用。
在下面的示例中,假设requests
数组中的三个项目之一失败了。
request(): Observable<T> {
const requests = [
this.getService$.getOne(),
this.getService$.getTwo(),
this.getService$.getThree()
]
return forkJoin(requests).pipe(
map(res => this.formatFunc(res))
);
}
代码应该是什么样子,以便在调用this.request()
时,即使其中一个服务失败并且必须再次获取数据,我仍然可以从所有三个服务中获取数据?
我进行了一些挖掘,发现人们正在添加this.getService$.getOne().catch(e => of([]))
...但这似乎只返回任何内容,而不是再次拨打电话。
我还使用retry
forkJoin(requests).pipe(
retry(3),
map(res => this.formatFunc(res))
)
但是会重试所有三个呼叫还是失败的一个?
答案 0 :(得分:2)
重试单个请求
const { forkJoin, of, throwError } = rxjs;
const { retry, tap } = rxjs.operators;
let retryCount = 0;
const requests = [
of(1),
of(2),
throwError('thrown error').pipe(
tap(
val => { console.log(val); },
error => {
console.log(retryCount ? `Retry ${retryCount}:` : 'First:', error);
retryCount++;
}
)
)
];
forkJoin(requests.map(request => request.pipe(retry(3)))).subscribe(
val => { console.log(val); },
error => { console.log('Sub:', error); }
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.3/rxjs.umd.min.js"></script>
答案 1 :(得分:1)
使用mergemap
import { of,forkJoin,throwError, } from 'rxjs';
import { retry,tap,mergeMap} from 'rxjs/operators';
let r1=of([1,2,3]).pipe(tap(()=>console.log("r1 called ..."))),
r2=of([4,5,6]).pipe(tap(()=>console.log("r2 called ..."))),
r3=of([7,8,9]).pipe(tap(()=>console.log("r3 called ...")));
of({})
.pipe(
mergeMap(
()=>forkJoin(r1,r2,r3,throwError("some error"))
),
tap({
next:()=>{
console.log("next...")
},
error:()=>{
console.log("error..");
}
}),
retry(3)
).subscribe();
这应该控制台error
4次。
这是与游乐场rxjs playground
的链接答案 2 :(得分:1)
但是,以上答案具有无效的错误处理,这种想法是正确的:您必须分开处理每个请求的错误。应该执行以下操作:
forkJoin([
request1.pipe(retryWhen(genericRetryStrategy())),
request2.pipe(retryWhen(genericRetryStrategy()))
])
示例中提到的genericRetryStrategy
可以从此处获取(作为示例):https://www.learnrxjs.io/operators/error_handling/retrywhen.html示例2:持续时间增加的可自定义重试。
您可以提供所需的任何其他逻辑代替