当参数timeout
为True时,我需要一个isTimeoutNeeded
运算符引发错误,以便我处理订阅的可观察对象在X秒后不发出任何值的情况。
if (isTimeoutNeeded) {
this.service.getData()
.pipe(
timeout(10000),
...
)
.subscribe((...) => ...);
} else {
this.service.getData()
.pipe(
...
)
.subscribe((...) => ...);
}
是否可以通过在需要时有条件地添加timeout
运算符来以rxjs的方式编写此代码?
我尝试使用iif
和switchMap
,但是没有用。
this.service.getData()
.pipe(
mergeMap((response) =>
iif(() => !isTimeoutNeeded,
of(response),
of(response).pipe(timeout(10000)) // did not apply timeout if isTimeoutNeeded = True
)
)
.subscribe((...) => ...);
switchMap
this.service.getData()
.pipe(
switchMap((response) => {
if (!isTimeoutNeeded) {
return of(response);
}
return of(response).timeout(10000); // did not apply timeout if isTimeoutNeeded = True
})
.....
)
)
.subscribe((...) => ...);
答案 0 :(得分:2)
您可以使用RxJs管道运算符delayWhen:
由提供的功能确定的延迟发射值。
让它返回一个interval()
可观察到的状态
.pipe(
delayWhen(() => isTimeoutNeeded ? interval(5000) ? interval(0)
)
答案 1 :(得分:2)
使用const subject = new BehaviorSubject(this.service.getData());
subject
.pipe(
switchMap(response => {
// If isTimeoutNeeded, a timetout is applied else wait result forever.
return isTimeoutNeeded
? response.pipe(timeout(10000))
: response;
}),
...
)
.subscribe(... => ...);
几乎是正确的:
getData
在这段代码中,超时应用于UICollectionView
可观察对象,而在您的示例中,这是一个新的可观察对象。
检查我的Stackblitz example。
答案 2 :(得分:2)
当操作员轻松描述行为而不详细说明实现时,RXJS效果最佳。当您开始使用switchMap()
和条件来表达 行为时,意图就消失了,代码也变得难以维护。
所以只需编写自己的运算符。
function timeoutWhen<T>(cond: boolean, value: number): OperatorFunction<T, T> {
return function(source: Observable<T>): Observable<T> {
return cond ? source.pipe(timeout(value)) : source;
}
}
现在,当您使用该运算符时,源代码将易于阅读和理解。
this.service.getData().pipe(
timeoutWhen(isTimeoutNeeded, 10000),
...
).subscribe((...) => ...);
现在,您可以重用某些东西,并使您的观测值更易于阅读和理解。
答案 3 :(得分:1)
对于这种特殊情况,我是这样做的:
.pipe(
(isTimeoutNeeded? interval(5000) : tap())
)
这里tap
最接近于没有任何运算符的运算符:)