【问题标题】:RxJS: Combining multiple http requests into single, flat observable arrayRxJS:将多个 http 请求组合成单个平面可观察数组
【发布时间】:2021-06-26 15:34:00
【问题描述】:

我在如何并行组合多个 http get 请求并将其作为平面、可观察数组返回时遇到问题。

目前,我有一个方法returnNewCars(),它在发出一个http get请求后返回Observable<ICar[]>——在方法returnAllCars()中,我想发出多个http get请求并仍然返回Observable<ICar[]>

现在,returnNewCars() 打印:

(2) [{…}, {…}]
0: {Make: "Honda", Model: "CRV", Year: "2021", Specifications: Array(5)}
1: {Make: "Toyota", Model: "Camry", Year: "2021", Specifications: Array(5)}
length: 2

我希望 returnAllCars() 以相同的格式打印,但要打印所有 6 个项目。

我关注RxJS doc regarding forkJoin 并尝试将其反映在我的代码中,但是,我不知道从那里着手。

app.component.ts

import { Component, OnInit } from '@angular/core';
import { CarsService } from './services/cars.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{

  title = 'AutoZone';

  constructor(private carsService: CarsService){
  }

  ngOnInit(): void {
  }
  
  testConsole(){
    this.carsService.returnNewCars().subscribe(newCars => console.log(newCars));
  }

}

cars.service.ts

import { HttpClient } from '@angular/common/http';
import { Injectable } from "@angular/core";
import { forkJoin, Observable } from 'rxjs';
import { concatMap, map, tap } from 'rxjs/operators';
import { ICar } from '../models/cars.model';

@Injectable({
    providedIn: 'root'
})

export class CarsService{
    carsURL = '/assets/cars.mock.json';
    newCarsURL = '/assets/cars.new.mock.json';
    preownedCarsURL = '/assets/cars.preowned.mock.json';
    usedCarsURL = '/assets/cars.used.mock.json';

    private newCars$: Observable<ICar[]>;

    //Store all http get request to new, preowned, used
    private allCars$: Observable<ICar[]>;

    constructor(private http : HttpClient){
    }
    
    returnNewCars(): Observable<ICar[]>{
        this.newCars$ = this.http.get<ICar[]>(this.newCarsURL);
        return this.newCars$;
    }

    returnAllCars(): Observable<ICar[]>{

        //How do I flatten to return Observable<ICar[]>?
        forkJoin(
            {
                new: this.http.get<ICar[]>(this.newCarsURL),
                preowned: this.http.get<ICar[]>(this.preownedCarsURL),
                used: this.http.get<ICar[]>(this.usedCarsURL)
            }
        )
        
        return null;
    }
}

【问题讨论】:

    标签: angular typescript rxjs observable subscribe


    【解决方案1】:

    您只需添加 .pipe(map(...)) 即可将 3 个单独的数组转换为一个数组。

    我看不出有什么理由需要将对象传递给forkJoin,你可以简单地传递一个数组:

    returnAllCars(): Observable<ICar[]>{
        return forkJoin([
            this.http.get<ICar[]>(this.newCarsURL),
            this.http.get<ICar[]>(this.preownedCarsURL),
            this.http.get<ICar[]>(this.usedCarsURL)
        ]).pipe(
            map(([new, preowned, used]) => [...new, ...preowned, ...used])
        );
    }
    

    另外,Observables 是惰性的,所以没有必要将它们包装在这样的方法中:

        returnNewCars(): Observable<ICar[]>{
            this.newCars$ = this.http.get<ICar[]>(this.newCarsURL);
            return this.newCars$;
        }
    

    你可以像这样简单地定义它:

    private newCars$ = this.http.get<ICar[]>(this.newCarsURL);
    

    所以,对于allCars(),您可以这样做:

    private allCars$ = forkJoin([this.newCars$, this.preOwnedCars$, this.usedCars$])
        .pipe(
            map(([new, preowned, used]) => [...new, ...preowned, ...used])
        );
    
    

    【讨论】:

      【解决方案2】:

      我不确定你为什么需要这个逻辑来用一种方法获取所有汽车,因为你应该调用 api 来分别获取 3 种汽车列表。无论如何,我尝试了一种方法来按您的预期获取 All 并使用 forkJoin。

      这里是stackblitz link

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-06
        • 1970-01-01
        • 2019-10-31
        • 1970-01-01
        • 2016-06-18
        • 1970-01-01
        • 2018-02-04
        • 2023-01-25
        相关资源
        最近更新 更多