Rxjs5:延迟创建一个可观察对象,直到另一个可观察对象发出一定的值



我正在尝试创建一个可观察的facebook jsdk,所以我有一个方法,与.create() d可观察对象,看起来像这样的例子

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还没有准备好。

我能做些什么来延迟这个可观察对象的创建?

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

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

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

注意,我使用switchMap,因为它清楚地表明,在任何时候只有一个getLoginStatus$()的实例是活动的。但是由于你的源只发出一次,你也可以使用mergeMapflatMap

p。我希望你们也可以打电话给complete(),而不仅仅是next()。这是一个很好的做法,告诉observable你已经用完了它们。

最新更新