创建可观察'once emitting'



我正在使用RxJS(版本6+)切换到另一个可观察对象,它需要发出一个值来启动管道(行)。

当前的解决方案是使用:

const saveAction$ = new Observable(observer => {
observer.next();
}).pipe(switchMap(() => this.saveAction()))

,它创建一个可观察对象,并立即发出。this.saveAction()返回一个Observable<void>,其中包含一些同步代码和对HttpClient调用的返回。saveAction$被保存在redux存储中,当另一个组件调度handleSaveChanges时,该存储将被调用。

另一个选项是使用of(true),但是true在这里没有值,因为它不会被使用。使用Subject将是另一种选择,但不需要主题的开销,因为我需要它只发出一次然后完成。

有一个EMPTY(https://rxjs-dev.firebaseapp.com/api/index/const/EMPTY)常量,它给出了一个完成但从不发出的可观察对象。如果有像ONCE这样的东西,而不是使用构造函数,那就好得多了。

有没有其他更干净的方法来解决这个问题?

EMPTY常量的定义是单行

export const EMPTY = new Observable<never>(subscriber => subscriber.complete());

您可以尝试定义您自己的ONCE如下

export const ONCE = new Observable<any>(subscriber => subscriber.next());

可以用作

ONCE.pipe(switchMapTo(this.saveAction()))

本质上和你的解是一样的。

评论你的想法

另一个选项是使用of(true),但是true没有值这里,因为它不会被使用

当你observer.next()时,它实际上也得到了一个值——undefined。它也没有被使用。因此,基于此,of(null)选项是一种简单而直接的方法。我不觉得这令人困惑,并且使用过这种方法很多次。

问题是,ONCE应该为一个值发出什么?必须提供这个值。消费者不需要这个值是另一回事,但是如果它调用next(),源必须提供一些的东西。

由于这个事实,我想写这个的最短方式是(正如你已经提到的)

of(true)

如果你需要更多的值,其中的值和/或计数是事先已知的,我会选择像

这样的东西
from([true, false, true, false])

或者使用预先创建数组的东西(循环,LINQ等)并使用this。

只有当你需要在运行时从不可观察的发出值时,我会采取一些Subject

使用

Observable2 = Observable1.pipe(first())

Observable只会发出第一个值,然后关闭自己。

如果我正确理解了你的需求:

如果this.saveAction()已经返回了一个可观察对象,为什么不返回它而不是new Observable(),并使用take(1)(docs),这样它只会发出一次?

像这样:

const saveAction$ = () => this.saveAction().pipe(take(1))

你可以在任何需要的地方使用this.saveAction()订阅:

saveAction$.subscribe()

最新更新