使用 Rxjs map 和 filter 一起从 json 中选择国家和州

Posted

技术标签:

【中文标题】使用 Rxjs map 和 filter 一起从 json 中选择国家和州【英文标题】:Using Rxjs map and filter together to select country and states from json 【发布时间】:2020-09-08 20:37:18 【问题描述】:

我有一个包含国家和州的 json 文件(作为示例):

 
  "countries": [
    
      "id": 1,
      "name": "United States"
    ,
    
      "id": 2,
      "name": "India"
    ],
  "states": [
    
      "id": 1,
      "countryId": 1,
      "name": "Alabama"
    ,
    
      "id": 2,
      "countryId": 1,
      "name": "Alaska"
     ] 

现在我有一个服务可以让国家和州稍后显示在我的下拉列表中:

export class CountriesService 

  constructor(private http: HttpClient)  

  public getCountries(): Observable<Country[]> 

    return this.http.get<Country[]>("assets/data.json").pipe(map(obj => obj["countries"]));

  

  public getStates(countryId: number): Observable<State[]> 
    return this.http.get<State[]>("assets/data.json").pipe(
      map(res => res["states"]), 
      map(res =>  if (res.countryId === countryId) return res;));

  

getCountries() 按预期工作,只返回Countries,但我无法从getStates 方法中获得基于countryId 的特定状态。

它什么也不返回。

我做错了什么?

【问题讨论】:

【参考方案1】:

您需要稍后在获取数据后对其进行过滤。

export class CountriesService 
  constructor(private http: HttpClient)  

  public getCountries(): Observable<Country[]> 
    return this.http.get<Country[]>("assets/data.json").pipe(
      map(obj => obj["countries"]),
    );
  

  public getStates(countryId: number): Observable<State[]> 
    return this.http.get<State[]>("assets/data.json").pipe(
      map(res => res["states"]), 
      withLatestFrom(of(countryId)),
      map((id, states) => states.filter(state.countryId === id)),
    );
  

您也可以将所有内容组合在一起以避免对不同状态的请求,因为它仍然是相同的数据。

export class CountriesService 

  constructor(private http: HttpClient)  

  public getCountriesWithStates(): Observable<Country[]> 
    return this.http.get<Country[]>("assets/data.json").pipe(
      map(data => data.countries.map(country => (
        ...country,
        states: data.states.filter(state => state.countryId === country.id),
      ))),
    );
  


service.getCountriesWithStates().subscribe(countries => 
// countries[0].states[0];
);

【讨论】:

我无法合并,因为当有人在下拉列表中选择国家/地区时,我需要根据国家/地区获取州。 这只是第二种选择。第一个单独获取它们。【参考方案2】:

虽然 API 调用的结果是一个 observable,但如果是由于 map 函数而不是 observable 数组,它会“发射”一个 observable。因此,您拥有的第二个地图功能并没有达到您的预期。相反,在您的第一张地图中,当您获取州时,您可以使用 javascript 数组中的一种方法(称为 filter),将州直至具有所需国家/地区 ID 的州。

public getStates(countryId: number): Observable<State[]>  return this.http.get<State[]>("assets/data.json").pipe( map(res => res["states"].filter(res => res.countryId === countryId)); 

【讨论】:

完美,只注意 countryId 是一个整数,所以我改为 "res.countryId === +countryId" 以使 "===" 起作用

以上是关于使用 Rxjs map 和 filter 一起从 json 中选择国家和州的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 rxjs 算子多次获取最近的值

#RXJS# 基础

RxJs - 将Observables数组转换为发射值数组

[RxJS] Learn How To Use RxJS 5.5 Beta 2

[Redux/Mobx] 你有了解Rxjs是什么吗?它是做什么的?

[RxJS] Filtering operator: filter