[英]How to filter an observable wrapped json file response?
I am working on a angular project and my task is to filter a huge file based on the "_type" key which can take different values.我正在处理一个 angular 项目,我的任务是根据可以采用不同值的“_type”键过滤一个大文件。 Right now I want to first filter _type = "COMPETITION".现在我想先过滤 _type = "COMPETITION"。
My model is defined in a competition.model.ts file which looks like this:我的模型是在一个如下所示的竞争.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"
}
Here is a my service class where I am trying to implement this:这是我正在尝试实现的服务类:
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;
});
}
}
I attached the snapshot of the result on my console, which doesn't really do what I really want to achieve.我在我的控制台上附加了结果的快照,这并没有真正实现我真正想要实现的目标。
I see multiple issues here我在这里看到多个问题
You're trying to fetch the asynchronous variable this.loadedCompetitions
synchronously.您正在尝试同步获取异步变量this.loadedCompetitions
。 It is not possible.这不可能。 All async variables should be accessed asynchronously.所有异步变量都应该异步访问。 You could use RxJS ReplaySubject
multicast observable with buffer 1 to hold and emit the last value.您可以使用带有缓冲区 1 的 RxJS ReplaySubject
多播可观察对象来保存和发出最后一个值。
You don't to manually loop through each item of the array and create a new array with the _type === 'COMPETITION'
property.您不必手动遍历数组的每个项目并使用_type === 'COMPETITION'
属性创建一个新数组。 You could use Array filter
function to filter out the objects based on a condition.您可以使用数组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
);
}
}
loadedCompetitions
variable to obtain notifications from it.现在您需要订阅loadedCompetitions
变量以从中获取通知。 I've used RxJS takeWhile
operator with Subject
to close any open subscriptions in the ngOnDestroy
hook of the component.我已经使用 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.