rxjs5:推迟创建一个可观察对象,直到另一个可观察对象发出特定值

rxjs5: defer creation of an observable until another observable emits certain value

我正在尝试创建一个 observable facebook jsdk,所以我有一个方法,.create()d observable 看起来像这样

getLoginStatus$() {
  return Observable.create((observer: Observer<FBResponseObject>) => {
    try {
      // this._fb is window.FB
      this._fb.getLoginStatus((resp: FBResponseObject) => {
        if (resp.error) {
          observer.error(resp.error);
        } else {
          observer.next(resp);
          observer.complete();
        }
      }, force);

    } catch (error) {
      observer.error(error);
    }

    return function () {};
  });
}

问题是,由于 facebook sdk 是异步加载的,所以在我订阅此方法时它可能仍然不可用。所以我有一个 Subject 叫做 fbSdkReady$next()true 一旦可用。现在的问题是如何连接这些,所以当我订阅 getLoginStatus$ 时,它首先等待 fbSdkReady$ 准备就绪,然后才创建可观察对象。

我尝试使用 delayWhen(() => fbSdkReady$.filter(r => !!r),它可以很好地等待 fbSdkReady$ 准备就绪,但是 Observable.create 被立即调用,因此出错,因为 FB还没准备好。

我可以做些什么来推迟创建那个 observable?

您已经有一个 fbSdkReady$。但是,如果我理解正确的话,它只会在 sdk 加载一次后发出。这是一个问题,因为如果您稍后订阅它,您将错过加载事件并且不知道您是否需要等待更长的时间或者它是否已经产生。一旦可用,您应该让流重复就绪值。您可以通过调用 fbSdkReady$.cache(1) 来完成此操作,但由于它由主题支持,您也可以将其替换为 new Rx.replaySubject(1).

现在我们解决了这个问题,您可以使用 fbSdkReady$ 作为 getLoginStatus$() 的基础。

fbSdkReady$.switchMap(() => getLoginStatus$())

请注意,我使用了 switchMap,因为它清楚地传达了任何时候只有一次 getLoginStatus$() 活动的实例。但是由于您的来源只发出一次,您也可以使用 mergeMapflatMap.

Ps。我希望您也就此问题致电 complete(),而不仅仅是 next()。向 Observables 发出您已完成使用它们的信号是一种很好的做法。