有条件地申请管道运营商

时间:2019-06-17 05:30:14

标签: angular rxjs

当参数timeout为True时,我需要一个isTimeoutNeeded运算符引发错误,以便我处理订阅的可观察对象在X秒后不发出任何值的情况。

if (isTimeoutNeeded) {
    this.service.getData()
      .pipe(
          timeout(10000),
          ...
      )
      .subscribe((...) => ...);
} else {
    this.service.getData()
    .pipe( 
       ... 
    )    
    .subscribe((...) => ...);
}

是否可以通过在需要时有条件地添加timeout运算符来以rxjs的方式编写此代码?

我尝试使用iifswitchMap,但是没有用。

 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((...) => ...);

4 个答案:

答案 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最接近于没有任何运算符的运算符:)