如何在 rxjs 管道中有条件地做某事?

How to do conditionally something in rxjs pipe?

有人能告诉我带条件操作的 rxjs 管道的正确语法是什么吗? 在这种情况下,如果环境名称数组长度不是 1,我想使用过滤器进行映射。如何在没有 return 的情况下使用 if 语句?有没有 rxjs 运算符?

environmentName = ['env1', 'env2'];

sourceList$ = this.getSources().pipe(
tap((srcList) => console.log(srcList)), //[["stylesheet","env1-xyz"],["include","cable"],...]
// if(this.environmentName.length!==1){
map((sourceList) => sourceList.filter((scr) => scr[1].startsWith(this.environmentName[0]) || scr[0] === 'include')),
//}
repeatWhen(() => this.sourceListChanged$)
);

Could somebody tell me what is the right syntax for an rxjs pipe with a conditional operation?

如果客户端软件已经从源管道传输,filter 是一种提供快速解决方案的工具。从过滤器返回 true 将继续管道。返回 false 将从管道中删除该值。返回 false 不影响底层订阅。

const source$ = /* snip */;
source$.pipe(
  filter((v) => v % 2 === 0) // non-even values do not continue
  tap((v) => {
    console.log("Even value received: ", v);
  })
).subscribe(
  /* snip */
)

如果需要新的来源,那么 iif 是合适的。

iif(
  () => someCondition, // if someCondition
  () => sourceA$, // then return sourceA
  () => sourceB$, // else return sourceB
).pipe(
  /* pipe the source returned from `iif` */
).subscribe(
  /* subscribe to the source returned from `iif` */
)

根据您的示例,您要检查的条件是数组的长度是 1 (false) 还是不是 (true)。

if the enviroment name array lenght is not 1

我已经将您在 CodePen 上的代码改编为一个独立的例子,这里是一个例子:

const environmentName = ['env1', 'env2'];
sourceList$.pipe(
  tap((sourceList) => console.log("Source list: ", sourceList)),
  filter(() => environmentName.length !== 1)
).subscribe(
  /* snip */
);

您的代码失败,因为您正在执行相反的检查。在您的示例中,仅当长度为 1 时管道才会继续。由于数组是硬编码的并且长度为 2,因此过滤器永远不会通过。

提到iif不是运算符。使用例如mergeMap 将其合并到您的代码中:

environmentName = ['env1', 'env2'];

const filterSourceListByEnv1OrInclude = srcList => srcList.filter((scr) => scr[1].startsWith(this.environmentName[0]) || scr[0] === 'include');

sourceList$ = this.getSources().pipe(
  tap((srcList) => console.log(srcList)),
  mergeMap(srcList => iff(
    () => this.environmentName.length !== 1,
    of(filterSourceListByEnv1OrInclude(srcList)),
    of(srcList)
  )),
  repeatWhen(() => this.sourceListChanged$)
);

或者可以使用三元运算符代替 iif:

sourceList$ = this.getSources().pipe(
  tap((srcList) => console.log(srcList)),
  mergeMap(srcList => of(this.environmentName.length !== 1
    ? filterSourceListByEnv1OrInclude(srcList)
    : srcList
  )),
  repeatWhen(() => this.sourceListChanged$)
);