在switchMap中使用result之前,等待Promise解析



我有以下断断续续工作的代码。有时getCurrentPosition承诺不能及时解析,undefined被传递给管道中的第一个switchMap,这当然会破坏一切。

位置服务:

// Get user location
public getUserLocation(): Observable<LocationModel> {
const options = {
enableHighAccuracy: true,
timeout: environment.userLocationTimeout
};
return from(Geolocation.getCurrentPosition(options)).pipe(
map((position) => {
const location = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
return location;
})
);
}

订阅页面:

// Get Subscriptions
private getSubscriptions(): void {
this.locationService
.getUserLocation()
.pipe(
switchMap((location: LocationModel) => this.locationAddressService.getAddress(location)),
switchMap((address: AddressModel) => this.subscriptionsService.getSubscriptions(address)),
takeUntil(this.destroy$)
)
.subscribe((subscriptions) =>
this.zone.run(() => {
this.subscriptions = subscriptions;
})
);
}

我期望from()只在承诺解决时返回LocationModel,但这似乎不是正在发生的事情。我用错了吗?我如何确保有一个为switchMap准备好的LocationModel ?

我们试图尽可能地远离承诺,因为它们会干扰我们的错误记录,所以我们试图尽可能地使用可观察对象。

另外,假设位置按时返回,我需要在NgZone内设置UI元素,如果我不这样做,那么在订阅返回后更新UI需要很长时间。我不认为这是同一个问题。

从你写的,我不得不假设你的承诺是解决与未定义。"right"解决这个问题的方法是找出导致Geolocation.getCurrentPosition解析为undefined的条件,并防止这些条件:

someCondition().then(_ =>
Geolocation.getCurrentPosition(options)
)

或使用RxJS:

defer(() => someCondition()).pipe(
switchMap(_ => Geolocation.getCurrentPosition(options)),
map((position) => ({
lat: position.coords.latitude,
lng: position.coords.longitude
})
)

如果难以调查,那么您可以重试,直到获得值。顺便说一句,将RxJS::from与承诺一起使用几乎总是错误的。你可以使用defer来统一承诺和RxJS的lazy语义。

defer(() => Geolocation.getCurrentPosition(options)).pipe(
tap(v => {
if(v == null) {
throw "error";
}
),
retry(_ => timer(500)),
map((position) => ({
lat: position.coords.latitude,
lng: position.coords.longitude
})
)

如果重试有效,我会将其升级到一个不会永远重试的版本. 我把那个练习留给你。

最新更新