繁体   English   中英

如何过滤可观察的包装 json 文件响应?

[英]How to filter an observable wrapped json file response?

我正在处理一个 angular 项目,我的任务是根据可以采用不同值的“_type”键过滤一个大文件。 现在我想先过滤 _type = "COMPETITION"。

我的模型是在一个如下所示的竞争.model.ts 文件中定义的:

export interface Competition {
  product: { active: true };
  schemaVersion: number;      // 2,
  status: string;             // PUBLISHED",
  comp: string;               // "4fc16b10-b8b4-4a99-b9f1-842f0d8b8413",
  _createdDate: number;       // 1594249198,
  discipline: string;         // "TRAP [ACTA]",
  categories: any;            // ["OPEN", "LADIES", "JUNIOR", "VETERAN", "CLAYS_ONLY"],
  host: string;               // "2",
  changeSet: number;          // 257,
  sync: number;               // 155,
  seq: number;                // 120,
  id: string;                 // "4fc16b10-b8b4-4a99-b9f1-842f0d8b8413",
  _type: string;              // "COMPETITION",
  when: number;               // 1597154400,
  title: string;              // "ACTA Self Nom Test"
}

这是我正在尝试实现的服务类:

import { Injectable, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs/Operators';
import { Competition } from '../interfaces/competition.model';

@Injectable ({providedIn: 'root'})

export class CompetitionListService {

  private loadedCompetitions: Competition[];
  private url = '../../assets/data/program1.json';

  constructor(private http: HttpClient) {}


  public getCompetitions(): Competition[] { return this.loadedCompetitions; }

  public fetchCompetition(){
    return this.http
    .get<Competition[]>(this.url)
      .pipe(
        map( (responseData) => {
          const competitionsArray = [];
          for (const key in responseData ) { // responseData is an object
            if (responseData.hasOwnProperty(key)) {
              // get the_type property
              // if ( key.valueOf() === 'COMPETITION') {
                competitionsArray.push(
                 // responseData[key]._createdDate,
                 responseData[key]._createdDate,
                  responseData[key]._type,
                  responseData[key].categories,
                  responseData[key].changeSet,
                  responseData[key].comp,
                  responseData[key].discipline,
                  responseData[key].host,
                  responseData[key].id,
                  responseData[key].product,
                  responseData[key].schemaVersion,
                  responseData[key].seq,
                  responseData[key].status
                );
            }

          }
          console.log(competitionsArray);
          return competitionsArray;
        })
      )
      .subscribe(competitions => {
          console.log(competitions);
          this.loadedCompetitions = competitions;
      });
  }
}

我在我的控制台上附加了结果的快照,这并没有真正实现我真正想要实现的目标。

代码结果的屏幕截图

我在这里看到多个问题

  1. 您正在尝试同步获取异步变量this.loadedCompetitions 这不可能。 所有异步变量都应该异步访问。 您可以使用带有缓冲区 1 的 RxJS ReplaySubject多播可观察对象来保存和发出最后一个值。

  2. 您不必手动遍历数组的每个项目并使用_type === 'COMPETITION'属性创建一个新数组。 您可以使用数组filter功能根据条件过滤掉对象。

...
import { Observable, ReplaySubject } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable ({providedIn: 'root'})
export class CompetitionListService {
  private loadedCompetitions: ReplaySubject<Competition[]> = new ReplaySubject<Competition[]>(1);
  private url = '../../assets/data/program1.json';

  constructor(private http: HttpClient) {
    this.fetchCompetition();      // <-- triggers the request and pushes value to `loadedCompetitions`
  }

  public getCompetitions(): Observable<Competition[]> { 
    return this.loadedCompetitions.asObservable(); 
  }

  public fetchCompetition() {        // return nothing here
    this.http.get<Competition[]>(this.url).pipe(
      map(res => res.filter(item => item['_type'] !== 'COMPETITION'))
    ).subscribe(
      res => this.loadedCompetitions.next(res),
      err => console.log(err)           // <-- handle error
    );
  }
}
  1. 现在您需要订阅loadedCompetitions变量以从中获取通知。 我已经使用 RxJS takeWhile运算符和Subject来关闭组件的ngOnDestroy钩子中的任何打开的订阅。
...
import { Observable, Subject } from 'rxjs';
import { takeWhile } from 'rxjs/operators';

export class SomeComponent implements OnInit, OnDestroy {
  private close$ = new Subject<any>();    // <-- use to close open subscriptions

  constructor(private competitionListService: CompetitionListService) { }

  ngOnInit() {
    this.competitionListService.loadedCompetitions.pipe(
      takeWhile(this.close$)
    ).subscribe(
      res => {
        console.log(res);
        // other statements that depend on `res`
      }
    );
  }

  ngOnDestroy() {
    this.close$.next();     // <-- close open subscriptions
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM