我正在尝试创建一个可观察的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$()
的实例是活动的。但是由于你的源只发出一次,你也可以使用mergeMap
或flatMap
。
p。我希望你们也可以打电话给complete()
,而不仅仅是next()
。这是一个很好的做法,告诉observable你已经用完了它们。