首页 > 解决方案 > 内部 observable 发出值后返回源 observable 值

问题描述

在一个可观察的链中,我需要执行一些异步工作,然后将源值返回到下一个可观察的,所以我必须pipe(mapTo(x))在异步工作之后。

一个更完整的例子:

// fake async work with just 1 null value
someAsyncWork = () => of(null)

of('1', '2', '3').pipe(
  // some async work
  concatMap(no => someAsyncWork().pipe(mapTo(no))),
  concatMap(no => `Some async work [${no}] done!`)
).subscribe(message => console.log(message))

我不能使用tap(no => someAsyncWork()),因为这会导致下一个 observable 在someAsyncWork()返回之前运行。

虽然我目前的方法有效,但它使代码有些混乱……而且我在代码库的许多地方都重复了这种模式。

pipe(mapTo(no))问题:无论如何要以更简洁/可读的方式做到这一点?

标签: rxjs

解决方案


也许最简单的做法是编写自己的可管道操作符。

例如:

const concatTap = <T>(project: (value: T) => Observable<any>) =>
  concatMap((value: T) => project(value).pipe(mapTo(value)));

但是,这假设异步操作的 observable 只发出一个值。为了防止发出多个值,您可以执行以下操作:

const concatTap = <T>(project: (value: T) => Observable<any>) =>
  concatMap((value: T) => concat(project(value).pipe(ignoreElements()), of(value)));

你可以这样使用concatTap

of('1', '2', '3').pipe(
  concatTap(() => someAsyncWork()),
  concatMap(no => `Some async work [${no}] done!`)
).subscribe(message => console.log(message));

我相信你可以选择一个比我更好的名字。concatTap是第一个出现在我脑海中的东西。命名事物是困难的。


推荐阅读