2017-06-03 30 views
3

我調用函數* ngFor聲明HTTP調用使用功能:無限循環,同時在* ngFor與異步管

@Component({ 
    selector: 'foo-view', 
    template: '<div *ngFor="let foo of loadAll() | async"></div>' 
}) 
export class FooComponent { 

    loadAll() : Observable<Foo[]> { 
    return this.http.get(`api/foos`) 
     .map(response => response.json() as Foo[]); 
    } 

} 

當代碼開始,它發送的無限循環一遍又一遍的http請求。

爲什麼? 我能做些什麼來避免這種情況?

P.S.我知道標準的解決方法,如

@Component({ 
    selector: 'foo-view', 
    template: '<div *ngFor="let foo of foos"></div>' 
}) 
export class FooComponent implements OnInit { 

    foos: Foo[] = []; 

    ngOnInit() { 
    loadAll().subscribe(foos => this.foos = foos); 
    } 

    loadAll() : Observable<Foo[]> { 
    return this.http.get(`api/foos`) 
     .map(response => response.json() as Foo[]); 
    } 

} 

但我正在尋找方法來刪除多餘的變量。

回答

4

這不是一個無限循環。每次Angular運行更改檢測器以檢查是否有任何綁定發生了更改,它需要運行使HTTP調用的方法loadAll()。這是因爲它不能確定它最後一次檢查沒有改變它。你顯然不想要這個。需要檢查更改的頻率可能很可能取決於其他組件(例如,它的父項)。

避免這種情況的一種方法正是您通過創建屬性foos: Foo[]顯示的內容。

如果你不想使用其他狀態變量,你可以作出這樣的重放緩存的數據可觀察到的鏈:

private cached; 

ngOnInit() { 
    this.cached = this.http.get(`api/foos`) 
    .map(response => response.json() as Foo[]) 
    .publishReplay(1) 
    .refCount() 
    .take(1); 
} 

,然後在模板你可以使用:

<div *ngFor="let foo of cached | async"></div> 

現在,它只會在開始時提出一個請求,每次訂閱時都會重播該值並完成。

此外,由於RxJS 5.4.0,您可以使用shareReplay(1)而不是.publishReplay(1).refCount()

順便說一下,您還可以使用changeDetection屬性更改組件上的更改檢測策略,以手動運行更改檢測。見ChangeDetectionStrategy,