RxJS 在执行 first 或 find 后不会执行管道运算符

RxJS won't execute pipe operators after executing either first or find with a false predicate

我有这个可观察的订阅

this.tooltipEventSubject.pipe(
    filter(event => event.type === "show"),
    tap(() => this.tooltipContent.loading = true),
    filter(() => this.messageContent?.sender !== undefined && this.tooltipContent.success === undefined),
    mergeMap(() => this.jabService.searchEntityInAddressBook(this.messageContent?.sender ?? "")),
    mergeMap(response => response.values),
    filter(response => response !== undefined) as OperatorFunction<Entity | undefined, Entity>,
    tap(() => console.log("before first")),
    find(entity => entity.name === this.messageContent?.sender),
    tap(() => console.log("after first")),
).subscribe({
    next: () => console.log("next"),
    error: err => console.log(err),
    complete: () => console.log("complete")
})

它命中“查找”谓词(使用调试器检查)然后什么都不做。

我尝试了很多运算符,比如先跟一个 catchError,在这个例子中我找到了。

它正在进入“before first”,但随后不会打印任何其他内容。我知道 find 谓词是 returning false,它应该。但为什么它会停止 运行 ?它不应该 return 对以下运算符“未定义”吗?它甚至不应该打印“完成”吗?

感谢您的回答

如果您的谓词 return 为假,这意味着没有符合您条件的值,并且 'find' 运算符在这种情况下不会 return 任何值。

查看官方 rxjs 文档了解更多信息:https://rxjs.dev/api/operators/find

find 运算符将等到谓词 returns 为真,直到那时它不会发出任何数据,即使 undefined.

find 仅当 source observable 完成 和 none 数据匹配时才会发出 undefined

在你的例子中,source observable 是一个表单事件,所以除非你这样做,否则它不会完成。Ex.takeUntil ..

我提供了两个例子。

Ex. 1

from([1, 2, 3, 4]).pipe(
  tap((data) => console.log('Before find', data)),
  find((data) => data > 5),
  tap((data) => console.log('After find', data))
)
.subscribe({
  next: console.log,
  error: console.error,
  complete: () => console.log('Completed'),
});

输出:

Before find 1

Before find 2

Before find 3

Before find 4

After find undefined

undefined

Completed

Ex. 2

<button id="btnFind">Find</button>
const btnFind = document.getElementById('btnFind');
let count: number = 0;
fromEvent(btnFind, 'click')
  .pipe(
    tap(() => count++),
    // takeUntil(timer(5000)),
    tap((count) => console.log('Before find', count)),
    find(() => count > 4),
    tap((count) => console.log('After find', count))
  )
  .subscribe({
    next: (e) => console.log(e),
    error: console.error,
    complete: () => console.log('Completed'),
  });

在第二个例子中它会在第 5 次点击后发出,或者如果你取消注释 takeUntil 然后在 5 秒后