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

时间:2017-09-03 19:51:41

标签: angular angular2-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"}然而,似乎传递给过滤器函数的函数参数 - transaction - 是整个事务数组,而不仅仅是我预期的单个事务对象 - 我应该如何安排代码过滤每个?我应该在这做什么呢?我见过的大多数例子看起来都像这样,所以我试图复制它们。

1 个答案:

答案 0 :(得分:1)

操作符所依据的可观察流是ENTIRE响应,在这种情况下是一个数据列表,而不是该列表中的元素。你只需要根据你想要的结果采取相应的行动......如果你希望列表中的每个项目都被转换为可观察流中的项目,那么他们会逐个通过运营商给最终的消费者,然后你这样做: / p>

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 - &gt; 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);
}

这只需要流中的数据数组并在其上运行常规数组过滤器方法并将其映射到过滤后的列表中。