Angular RxJS:到达第一个时,两个嵌套的 https 和更新组件 [英] Angular RxJS: two nested https and update component when first one is reach

查看:29
本文介绍了Angular RxJS:到达第一个时,两个嵌套的 https 和更新组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要执行两个 http 请求.一个接一个,因为第一个提供的值将用于进行其他 http 调用.

我还需要在第一个 http 解析后更新我的组件.而且同样,当第二个 http 也被解析时更新它.

interface Vehicle {只读 ID:字符串;只读名称:字符串;只读品牌:字符串;}

第一个 http 调用获取 name,另一个获取 brand.

猜猜这个html组件:​​

<div *ngFor='let Vehicle of Vehicles$ |异步'>{{vehicle.name}} - {{vehicle.brand}}

在控制器中:

vehicles$: Observable>ngOnInit() {this.vehicles$ = this._vehicleService.getVehicles();//怎么继续???}

where getVehicles:

getVehicles(): Observable>{返回 http.get("url").map(vehicle => {id: Vehicle.id, name: Vehicle.name});}getVehicleBrand(ids: Array): Observable>{//根据 ids 参数构建 url返回 http.get("url").map(brand => {id:brand.vehicle_id,brand.name});}

如何将 VehicleVehicleBrand 合并?

解决方案

合并请求之间的数据不应该是组件的责任.这就是服务的用途.

此类服务的外观示例(当然,您可以根据自己的需要随意定制):

const vehicleIdNameMock: VehicleIdName[] = [{ id: 'vehicle-1', name: 'Vehicle 1' },{ id: 'vehicle-2', name: 'Vehicle 2' },{ id: 'vehicle-3', name: 'Vehicle 3' },];const VehicleIdToBrandMap: { [key: string]: VehicleIdBrand } = {'vehicle-1': { id: 'vehicle-1', 品牌: '品牌 A' },'vehicle-2': { id: 'vehicle-2', 品牌: '品牌 A' },'vehicle-3': { id: 'vehicle-3', 品牌: 'Brand B' },}@Injectable()出口类 VehiclesService {private getVehiclesIdName(): Observable{返回(vehiclesIdNameMock).管道(延迟(500));}private getVehicleIdBrand(id: string): Observable{返回(vehiclesIdToBrandMap[id]).pipe(delay(500));}public getVehicles(): Observable{返回 this.getVehiclesIdName().pipe(合并地图(车辆IdName => {const 请求:Observable[] = vehicleIdName.map(vehicleIdName => this.getVehicleIdBrand(vehicleIdName.id))返回 forkJoin(requests).pipe(地图(车辆IdBrand => 车辆IdBrand.map((vehiclesIdBrand, 索引) =>({ ...vehiclesIdBrand, ...vehiclesIdName[index] }))));}))}}

这里的 2 个私有方法被嘲笑,因为我显然无权访问您的端点,但只要您返回相同的数据类型就可以了.

那么你的 VehicleComponent 就会像:

@Component({选择器:应用车辆",templateUrl: './vehicles.component.html',styleUrls: ['./vehicles.component.css']})导出类 VehiclesComponent {公共车辆$: Observable= this.vehiclesService.getVehicles();构造函数(私人车辆服务:车辆服务){}}

这是关于 Stackblitz 的现场演示 https://stackblitz.com/edit/angular-et3oug

I need to perform two http requests. One after first one, since values provided by first one are going to be used to make the other http calls.

I also need to update my component when first http is resolved. And also, updated it when second http is also resolved.

interface Vehicle {
    readonly id: string;
    readonly name: string;
    readonly brand: string;
}

First http call is getting name, and the other one the brand.

Guess this html component:

<div *ngFor='let vehicle of vehicles$ | async'>
    {{vehicle.name}} - {{vehicle.brand}}
</div>

In controller:

vehicles$: Observable<Array<Vehicle>>
ngOnInit() {
    this.vehicles$ = this._vehicleService.getVehicles();
    // how to go on???
}

where getVehicles:

getVehicles(): Observable<Array<Vehicle>> {
    return http.get("url")
        .map(vehicle => <Vehicle>{id: vehicle.id, name: vehicle.name});
}

getVehicleBrand(ids: Array<String>): Observable<Array<VehicleBrand>> {
   // build url according ids parameter
   return http.get("url")
       .map(brand => <VehicleBrand>{id: brand.vehicle_id, brand.name});
}

How could I merge Vehicle with VehicleBrand?

解决方案

Merging data between requests shouldn't be the responsibility of the component. That's what services are for.

Example of what such a service might look (feel free to customize it according to your own needs of course):

const vehiclesIdNameMock: VehicleIdName[] = [
  { id: 'vehicle-1', name: 'Vehicle 1' },
  { id: 'vehicle-2', name: 'Vehicle 2' },
  { id: 'vehicle-3', name: 'Vehicle 3' },
];

const vehiclesIdToBrandMap: { [key: string]: VehicleIdBrand } = {
  'vehicle-1': { id: 'vehicle-1', brand: 'Brand A' },
  'vehicle-2': { id: 'vehicle-2', brand: 'Brand A' },
  'vehicle-3': { id: 'vehicle-3', brand: 'Brand B' },
}

@Injectable()
export class VehiclesService {
  private getVehiclesIdName(): Observable<VehicleIdName[]> {
    return of(vehiclesIdNameMock).pipe(delay(500));
  }

  private getVehicleIdBrand(id: string): Observable<VehicleIdBrand> {
    return of(vehiclesIdToBrandMap[id]).pipe(delay(500));
  }

  public getVehicles(): Observable<Vehicle[]>{
    return this.getVehiclesIdName().pipe(
      mergeMap(vehiclesIdName => {
        const requests: Observable<VehicleIdBrand>[] = vehiclesIdName.map(vehicleIdName => this.getVehicleIdBrand(vehicleIdName.id))

        return forkJoin(requests).pipe(
          map(vehiclesIdBrand => vehiclesIdBrand.map(
            (vehiclesIdBrand, index) => ({ ...vehiclesIdBrand, ...vehiclesIdName[index] })
          ))
        );
      })
    )
  }
}

The 2 private methods here are mocked because I obviously don't have access to your endpoint but as long as your return the same data type that'll be fine.

Then your VehicleComponent would be as clean as:

@Component({
  selector: 'app-vehicles',
  templateUrl: './vehicles.component.html',
  styleUrls: ['./vehicles.component.css']
})
export class VehiclesComponent {
  public vehicles$: Observable<Vehicle[]> = this.vehiclesService.getVehicles();

  constructor(private vehiclesService: VehiclesService) {}
}

Here's a live demo on Stackblitz https://stackblitz.com/edit/angular-et3oug

这篇关于Angular RxJS:到达第一个时,两个嵌套的 https 和更新组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆