如何使用 Angular 2 HTTP 过滤 API 响应?

How to filter API response with Angular 2 HTTP?

这是我的交易API回复:

[{
   "id": 1,
   "description": "Sandwich",
   "date": "2017-09-01",
   "category": "Take away",
   "tags": ["Holidays"],
   "amount": -2
},{
   "id": 2,
   "description": "Wage",
   "date": "2017-08-31",
   "category": "Wage",
   "tags": [],
   "amount": 2000
}]

我的 Angular 服务中有以下代码:

@Injectable()
export class TransactionsService {
    private _transactionssurl = 'app/transactions/transactions.json';

    constructor(private _http: Http){}

    getTransactions(query = {}): Observable<ITransaction[]> {
        return this._http.get(this._transactionssurl)
            .map((response: Response) => <ITransaction[]> response.json())
            .filter((value: any) => {
                console.log(value)
                if (query["month"] && transaction["month"].indexOf(query["month"]) === 0 ) return false;
                if (query["category"] && transaction["category"] !== query["category"]) return false;
                if (query["tag"] && transaction["tags"].includes(query["tag"])) return false;
                return true;
            })
            .do(data => console.log(data))
            .catch(this.handleError);
    }

    //...

}

你可以在上面看到我正在尝试根据传入的查询对象过滤数据,例如{month: "2017-09", tag: "Holidays"} 但是,传递给过滤器函数的函数参数 - 交易 - 似乎是整个交易数组,而不是我预期的单个交易对象 - 我应该如何安排代码分别过滤?我应该在这里做什么呢?我看到的大多数示例看起来有点像这样,所以我尝试复制它们。

运算符作用的可观察流是整个响应,在本例中是一个数据列表,而不是该列表中的元素。您只需要根据您想要的结果采取相应的行动......如果您希望列表中的每个项目都转换为可观察流中的项目,那么他们一个一个地通过运营商到达最终消费者然后你这样做:

getTransactions(query = {}): Observable<ITransaction[]> {
    return this._http.get(this._transactionssurl)
        .map((response: Response) => <ITransaction[]> response.json())
        .flatMap(data => Observable.from(data))
        .filter((value: any) => {
            console.log(value)
            if (query["month"] && transaction["month"].indexOf(query["month"]) === 0 ) return false;
            if (query["category"] && transaction["category"] !== query["category"]) return false;
            if (query["tag"] && transaction["tags"].includes(query["tag"])) return false;
            return true;
        })
        .do(data => console.log(data))
        .catch(this.handleError);
}

flatMap -> from 操作获取您的列表数据并将其展平为可观察的流。但是,如果您实际上希望最终消费者的整个列表在一个可观察的流项目中,这是没有意义的,因为您必须在最后使用 reduce 运算符重新聚合响应,例如:

 .reduce((acc, val) => acc.concat([val]), [])

如果你只是想过滤列表并传递它,很简单:

getTransactions(query = {}): Observable<ITransaction[]> {
    return this._http.get(this._transactionssurl)
        .map((response: Response) => <ITransaction[]> response.json())
        .map((list: any) => {
            return list.filter(value => {
                if (query["month"] && transaction["month"].indexOf(query["month"]) === 0 ) return false;
                if (query["category"] && transaction["category"] !== query["category"]) return false;
                if (query["tag"] && transaction["tags"].includes(query["tag"])) return false;
                return true;
            });
        })
        .do(data => console.log(data))
        .catch(this.handleError);
}

这只是需要流中的数据数组,并对其运行普通数组过滤方法并将其映射到过滤列表中。