在 RxJS 中对 Observable<void> 调用观察者.next()

Run*_*e G 5 rxjs angular

我正在创建一个使用 RxJS Observable 的模块,其中一些方法正在返回Observable<void>. 我现在已经搜索了很多,但是在完成Observable<void>.

所以问题很简单,应该next为这些 observable 发出回调,还是只是complete回调?

在我看来,只调用 似乎是最干净的complete,但Observable<T>.subscribe()complete作为最后一个参数,这使得用户使用起来更加复杂。

以这个代码示例作为问题的说明:

doSomethingIgnorableUnlessError(): Observable<void> {
  return Observable.create((observer: Observer<void>) => {
    if (executeIgnorable()) {
      // should observer.next(null); be called here?
      observer.next(null); 
      observer.complete();
    } else {
      observer.error('something that shouldn't be ignored occurred');
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

mar*_*tin 6

就我个人而言,我的方法是,如果你有Observable<void>它就意味着它会发射,但它的值并不重要。您仍然可以调用next(),但要明显表明您没有传递任何应该使用的值void 0

subject.next(void 0);
Run Code Online (Sandbox Code Playgroud)

然后使用这个Subject就像任何其他Observable一样,你只需忽略值本身:

subject.subscribe(() => ...);
Run Code Online (Sandbox Code Playgroud)

null这里重要的是,这与使用or不同undefined。例如,您可以Observable<number>调用observer.next(null)or observer.next(undefined)( https://stackblitz.com/edit/rxjs6-demo-jtwymx?file=index.ts ),即使它没有意义。你想要一个number,但如果你收到了,undefined你可能会遇到奇怪的行为。例如undefined + 4NaN.

我认为一个典型的用例Observable<void>是无限滚动。当您滚动到页面末尾时,您想要加载更多数据,因此您可以subject.next(void 0)在显然该值并不重要的地方调用。它仅用于触发加载更多项目。


Sco*_*ers 4

AnObservable适合在您想要响应可能变化的数据流时使用。上面的函数doSomethingIgnoreUnlessError()将返回一个可观察对象,您可以.subscribe()使用回调函数;该函数将在每次 Observable 调用时执行.next()。在这种情况下,Observable<void>您可以在订阅回调中省略数据有效负载函数参数,如下所示:

doSomethingIgnorableUnlessError().subscribe(() => {
    // do something; without data it's just an event
}).catch(err => {
    // handle error condition from returned Observable
});
Run Code Online (Sandbox Code Playgroud)

最终,您需要.next()至少调用一次,以便该可观察对象的任何订阅者都能收到事件并触发.subscribe(). 使用 会.complete()产生一个不同的事件,可以从返回的 Observable 中挂钩,并且不支持传递任何数据;所以这或多或少是您响应的事件。

我们可以使用该方法的可选参数来说明和简化这一点.subscribe(),如下所示:

doSomethingIgnorableUnlessError().subscribe(() => {
    // do something; without data it's just an event
}, err => {
    // handle error condition from returned Observable
}, () => {
    // handle subscription complete (no more data coming)
});
Run Code Online (Sandbox Code Playgroud)

它捕获所有三个内容 - 订阅数据、错误和完成事件。如果您从未在 observable 中调用.next(),则订阅回调(第一个参数)永远不会触发,并且编写仅发送完成事件的 Observable 有点不直观。如果这就是您所需要的,并且您必须使用 Observable,那么建议将其转换为始终一次性使用的 Promise。甚至还有一个内置.toPromise()的适合这样的场合!

因此,TL;DRnull - 如果您忽略传递到返回的 Observable 的.next()数据,则传递给并不重要,并且如果您希望终止数据流并取消,则只能在 Observable 中手动调用所有订阅。如果您的 Observable 需要推送另一个更改值,请不要调用!.subscribe().complete().complete()