如何 "combine" 3 个或更多 Observables?
How to "combine" 3 or more Observables?
我有来自 3 个不同服务的这 3 个 Observable(3 个 API 调用):
this.gs.getLocationName().subscribe((loc) => this.locationName = loc);
this.gs.getLocationInfo(this.locationName).subscribe((data) => {
this.lat = data.results.geometry.location.lat;
this.lon = data.results.geometry.location.lng;
});
this.ws.getWeatherByCoordinates(this.lat, this.lon).subscribe((data) => ...);
如你所见,它依赖于之前的 Observable,所以我想 运行 一个一个地
例如,我知道如何将 2 Observable 与管道和 mergeMap“结合”,但是 3
有问题
我的解决方案是这样的:
this.gs
.getLocationName()
.pipe(
tap((loc) => {
this.locationName = loc;
}),
mergeMap((loc) => {
return this.gs.getLocationInfo(this.locationName);
})
)
.pipe(
tap((data) => {
this.lat = data.results[0].geometry.location.lat;
this.lon = data.results[0].geometry.location.lng;
})
)
.subscribe((data) => {
this.ws.getWeatherByCoordinates(this.lat, this.lon).subscribe((data) => ...);
});
虽然我不确定在订阅中订阅是否是好的做法,但它有效?
所以我的下一个解决方案是:
this.gs
.getLocationName()
.pipe(
tap((loc) => {
this.locationName = loc;
}),
mergeMap((loc) => {
return this.gs.getLocationInfo(this.locationName);
})
)
.pipe(
tap((data) => {
this.lat = data.results[0].geometry.location.lat;
this.lon = data.results[0].geometry.location.lng;
}),
concatMap((data) => {
return this.ws.getWeatherByCoordinates(this.lat, this.lon);
})
)
.subscribe((data: WeatherModel) => {
...
});
这也行,但我也不确定我是否做对了。不确定 concatMap 是否是 goo 的方式,但它至少对我有用。
有什么技巧可以提高我的代码质量吗?
你做得很好,继续mergeMap
。你可以 mergeMap
多个 Observable
this.gs.getLocationName().pipe(
tap(loc => this.locationName = loc),
mergeMap(locationName => this.gs.getLocationInfo(locationName)),
tap(data => {
this.lat = data.results.geometry.location.lat;
this.lon = data.results.geometry.location.lng;
}),
mergeMap(data => this.ws.getWeatherByCoordinates(this.lat, this.lon))
).subscribe((data) => {
...
});
此外,如果您不使用属性 locationName
、lat
和 lon
,您可以将上面的内容减少到
this.gs.getLocationName().pipe(
mergeMap(loc => this.gs.getLocationInfo(locationName)),
map(data => ({
lat : data.results.geometry.location.lat,
lon : data.results.geometry.location.lng;
})),
mergeMap(({lat, lon}) => this.ws.getWeatherByCoordinates(lat, lon))
).subscribe((data) => {
...
});
我有来自 3 个不同服务的这 3 个 Observable(3 个 API 调用):
this.gs.getLocationName().subscribe((loc) => this.locationName = loc);
this.gs.getLocationInfo(this.locationName).subscribe((data) => {
this.lat = data.results.geometry.location.lat;
this.lon = data.results.geometry.location.lng;
});
this.ws.getWeatherByCoordinates(this.lat, this.lon).subscribe((data) => ...);
如你所见,它依赖于之前的 Observable,所以我想 运行 一个一个地
例如,我知道如何将 2 Observable 与管道和 mergeMap“结合”,但是 3
有问题我的解决方案是这样的:
this.gs
.getLocationName()
.pipe(
tap((loc) => {
this.locationName = loc;
}),
mergeMap((loc) => {
return this.gs.getLocationInfo(this.locationName);
})
)
.pipe(
tap((data) => {
this.lat = data.results[0].geometry.location.lat;
this.lon = data.results[0].geometry.location.lng;
})
)
.subscribe((data) => {
this.ws.getWeatherByCoordinates(this.lat, this.lon).subscribe((data) => ...);
});
虽然我不确定在订阅中订阅是否是好的做法,但它有效?
所以我的下一个解决方案是:
this.gs
.getLocationName()
.pipe(
tap((loc) => {
this.locationName = loc;
}),
mergeMap((loc) => {
return this.gs.getLocationInfo(this.locationName);
})
)
.pipe(
tap((data) => {
this.lat = data.results[0].geometry.location.lat;
this.lon = data.results[0].geometry.location.lng;
}),
concatMap((data) => {
return this.ws.getWeatherByCoordinates(this.lat, this.lon);
})
)
.subscribe((data: WeatherModel) => {
...
});
这也行,但我也不确定我是否做对了。不确定 concatMap 是否是 goo 的方式,但它至少对我有用。
有什么技巧可以提高我的代码质量吗?
你做得很好,继续mergeMap
。你可以 mergeMap
多个 Observable
this.gs.getLocationName().pipe(
tap(loc => this.locationName = loc),
mergeMap(locationName => this.gs.getLocationInfo(locationName)),
tap(data => {
this.lat = data.results.geometry.location.lat;
this.lon = data.results.geometry.location.lng;
}),
mergeMap(data => this.ws.getWeatherByCoordinates(this.lat, this.lon))
).subscribe((data) => {
...
});
此外,如果您不使用属性 locationName
、lat
和 lon
,您可以将上面的内容减少到
this.gs.getLocationName().pipe(
mergeMap(loc => this.gs.getLocationInfo(locationName)),
map(data => ({
lat : data.results.geometry.location.lat,
lon : data.results.geometry.location.lng;
})),
mergeMap(({lat, lon}) => this.ws.getWeatherByCoordinates(lat, lon))
).subscribe((data) => {
...
});