RxJS:将多个 http 请求组合成单个平面可观察数组
RxJS: Combining multiple http requests into single, flat observable array
我遇到了如何并行组合多个 http get 请求并将其return作为平面、可观察数组的问题。
目前,我有一个方法,returnNewCars()
,在发出一个 http get 请求后 returns Observable<ICar[]>
-- 在方法 returnAllCars()
中,我想发出多个 http get 请求并且仍然 return 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;
}
}
我不确定你为什么需要这个逻辑来用一种方法获取所有汽车,因为你应该调用 api 来分别获取 3 种汽车列表。无论如何,我尝试了一种方法来获得 All 正如你所期望的那样并使用了 forkJoin.
您只需添加一个 .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])
);
我遇到了如何并行组合多个 http get 请求并将其return作为平面、可观察数组的问题。
目前,我有一个方法,returnNewCars()
,在发出一个 http get 请求后 returns Observable<ICar[]>
-- 在方法 returnAllCars()
中,我想发出多个 http get 请求并且仍然 return 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;
}
}
我不确定你为什么需要这个逻辑来用一种方法获取所有汽车,因为你应该调用 api 来分别获取 3 种汽车列表。无论如何,我尝试了一种方法来获得 All 正如你所期望的那样并使用了 forkJoin.
您只需添加一个 .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])
);