【问题标题】:How to "combine" 3 or more Observables?如何“组合” 3 个或更多 Observables?
【发布时间】:2021-07-12 17:28:15
【问题描述】:

我有来自 3 个不同服务的这 3 个 Observables(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 的方法,但至少对我有用。

有什么技巧可以提高我的代码质量吗?

【问题讨论】:

标签: javascript angular typescript observable


【解决方案1】:

你做得很好,继续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) => {
  ...
});

此外,如果您不使用属性locationNamelatlon,您可以将上述内容缩减为

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) => {
  ...
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多