2017-09-03 95 views
0

這是我的事務API響應:如何使用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 
}] 

我在我的角度服務下面的代碼:

@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"}然而,函數參數 - 事務 - 它被傳遞到過濾器函數是整個事務數組,而不僅僅是一個單一的事務對象,這是我的預期 - 我應該如何安排代碼來過濾每個單獨的?我應該在這裏做什麼呢?我見過的大多數例子都是這樣的,所以我試圖複製它們。

+0

您正在調用'Observable.filter',它過濾事件流**,而不是**'Array.filter'。 – jonrsharpe

+0

您正試圖過濾observable(即由observable發出的事件),而不是過濾observable發出的數組元素。在從響應中提取數組後,過濾應該在傳遞給map()的回調函數**內部。 –

回答

1

您操作員操作的可觀察流是ENTIRE響應,在本例中是一個數據列表,而不是該列表中的元素。你只需要根據你想要的結果採取相應的行動......如果你想讓列表中的每個項目都被轉化爲可觀察的流中的項目,那麼他們會一個接一個地通過運營商到最終消費者,那麼你可以這樣做:

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 operation將您的列表數據放到一個可觀察的流中。但是,這是沒有意義的,如果你真的想在一個可觀察數據流的項目在您的最終消費者的整個列表,你將不得不重新聚集在像到底有降低運營商的反應:

.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); 
} 

這只是預計流中的數據數組並運行正常濾鏡陣列方法上,並將其映射到過濾列表。

+0

感謝您的非常詳細的回覆。我試圖從地圖調用中的另一種方法,而不是鏈接過濾器()到,所以response.json()。filter(...),我猜是類似的?我看到你已經鏈接了另一個map()調用,雖然看起來有點整潔。 – Martyn

+0

我的偏好是讓每個操作員儘可能少地做個別操作。我認爲當你幾個月後回來時,代碼更清晰,更容易理解和維護,忘記你爲什麼做了你所做的事情 – bryan60