我可以将 async/await Promises 与可观察的 RXJS 混合使用吗?
Posted
技术标签:
【中文标题】我可以将 async/await Promises 与可观察的 RXJS 混合使用吗?【英文标题】:Could I mix async/await Promises with observable RXJS? 【发布时间】:2019-06-09 15:05:16 【问题描述】:我正在使用 ionic/angular 和 RXJS observables。
我正在尝试使用 Rxjs observables 重构我的代码,并且我有下一个代码:
ionViewWillEnter()
if (this.platform.is('core') || this.platform.is('mobileweb'))
this.lat = 37.3675506;
this.lng = -6.0452695;
this.printMap();
else
if (this.platform.is('android'))
this.tryGeolocation();
else if (this.platform.is('ios'))
console.log("IOS")
如果用户从 android 手机访问,我应该检查:isLocationAuthorized、isLocationEnabled() 以使用 getCurrentPosition() 获取当前位置,然后我必须在使用 Observables forkjoin 的地方打印地图。
问题是检查方法返回承诺,我不知道如何链接这个流程。
tryGeolocation 是下一个:
async tryGeolocation()
try
if (await this.diagnostic.isLocationAuthorized())
if (await this.diagnostic.isLocationEnabled())
this.loading = this.loadingCtrl.create(
content: 'Localizando...',
dismissOnPageChange: true
);
this.loading.present();
const coords = await this.geolocation.getCurrentPosition();
this.lat = coords.latitude;
this.lng = coords.longitude;
this.loading.dismiss();
alert(this.lat);
alert(this.lng);
this.printMap();
else
console.log("error1")
else
console.log("error2")
catch (e)
console.log('Error getting location', e);
printMap()
let obs1 = this._sp.getLocationsByPosition(this.lat, this.lng);
let obs2 = this._sp.getUserFavoriteLocations2();
this.subscription = forkJoin([obs1, obs2]).subscribe(results =>
this.allLocations = results[0];
this.myLocations = results[1];
this.allLocations = this.allLocations.filter(item => !this.myLocations.some(other => item.id.sid_location === other.id.sid_location && item.id.bid_environment === other.id.bid_environment));
this.map = new google.maps.Map(this.mapElement.nativeElement,
zoom: 13,
center: lat: parseFloat(this.lat), lng: parseFloat(this.lng),
zoomControl: true,
draggable: true
);
new google.maps.Marker(
position: lat: parseFloat(this.lat), lng: parseFloat(this.lng),
map: this.map,
icon:
url: "https://maps.gstatic.com/mapfiles/api-3/images/spotlight-poi2_hdpi.png"
);
this.printMarkers();
);
我尝试将 promise 转换为这样的 observables:
let obs1 = Observable.fromPromise(this.diagnostic.isLocationAuthorized());
let obs2 = Observable.fromPromise(this.diagnostic.isLocationEnabled());
let obs3 = Observable.fromPromise(this.geolocation.getCurrentPosition());
obs1.flatMap(() => obs2)
.flatMap(() => obs3)
.subscribe(coords =>
console.log(coords);
//CALL TO printMap?
)
有人可以帮助我实现重构代码的流程吗?
提前谢谢你
【问题讨论】:
你能用Promise.all()
吗? developer.mozilla.org/en-US/docs/Web/javascript/Reference/…
您能否将此示例简化为可重现的内容? ***.com/help/mcve
@AlexK 我不这么认为,因为正如您在 tryGeoLocation 上看到的那样,一个依赖于另一个
【参考方案1】:
Rxjs observables and Promises 。 Defer docs.
话虽如此,fromPromise
已被弃用,它不再出现在 documentation 中。使用from
to get an observable from a promise。
import from from 'rxjs';
let obs1 = from(this.diagnostic.isLocationAuthorized());
let obs2 = fromPromise(this.diagnostic.isLocationEnabled());
let obs3 = fromPromise(this.geolocation.getCurrentPosition());
但是考虑一下它是否值得您的用例。 This answer would help you to decide.
事实证明,您可以将 async-await 与 observables 混合使用,但这并不意味着它适合您的用例。 (谨慎使用此代码)
import defer from 'rxjs';
defer(async function()
const a = await promiseDelay(1000).then(() => 1);
const b = a + await promiseDelay(1000).then(() => 2);
return a + b + await promiseDelay(1000).then(() => 3);
)
.subscribe(x => console.log(x)) // logs 7
【讨论】:
你写了 « Async-await 和 Observables 不能一起工作。 » 你链接的页面说 « RxJS 从一开始就与 Promises 具有高度的互操作性。 »,继续详细解释他们如何确实协同工作...【参考方案2】:您可以使用 from
和 combineLatest
来 rxjs-ify 您的承诺链。我在这里发布了一个 stackblitz 示例 - https://stackblitz.com/edit/rxjs-jnrj37?devtoolsheight=60
基本上是这样的:
import combineLatest, from, of from "rxjs";
import map from "rxjs/operators";
const promiseMaker = timeInMS =>
new Promise((resolve, reject) =>
setTimeout(() =>
console.log("promise done");
resolve("foo");
, timeInMS);
);
const promise1$ = from(promiseMaker(300));
const promise2$ = from(promiseMaker(500));
const promise3$ = from(promiseMaker(800));
combineLatest(promise1$, promise2$, promise3$).subscribe(() =>
console.log("Ready!!!")
);
如果 Promise 相互依赖,则可以使用 switchMap
或 mergeMap
代替 combineLatest
并根据需要链接它们
【讨论】:
以上是关于我可以将 async/await Promises 与可观察的 RXJS 混合使用吗?的主要内容,如果未能解决你的问题,请参考以下文章
Angular 8 - 如何使用 Promises 和 Async/Await [重复]
使用 Javascript(以及 Node.js)使用 async/await 和 Promises 的正确方法是啥 [重复]
6 Reasons Why JavaScript’s Async/Await Blows Promises Away (Tutorial)
现代JS中的流程控制:详解Callbacks Promises Async/Await