2016-09-01 29 views
5

假設我想從商店檢索一組記錄,並使用*ngFor(例如,如何使用RxJS和Angular2構建真正的可觀察集合?

<ul> 
    <li *ngFor="let record in records | async"> 
     ... 
    </li> 
</ul> 

現在,用戶點擊「新建...」按鈕,另一個記錄添加到存儲和

recordAdded: EventEmitter<string>; 

火災告訴我的位置。因此,我從商店獲得新唱片 - 只有唱片 - 哎呀,我如何讓我的*ngFor顯示這個額外的唱片?

好了,我可以保持所有記錄在陣列,例如

_records: Record[]; 

,並通過訂閱Observable<Record[]>

this.recordService.getAll().subscribe(r => this._records = r); 

填補這個數組,但這個數組需要有一個Observable本身以便在有新的記錄時通知消費者。所以

observableRecords = Observable.create(obs => { 
    this.recordService.getAll().subscribe(rec => { 
     this._records = rec; 
     obs.next(rec); 
     // Got the array published, now waiting for events 
     this.recordAdded.subscribe(rec => { 
      this._records.push(rec); 
      obs.next(this._records); 
     });    
    }); 
}); 

啊...這不僅是痛苦的看,也有一噸的開銷作爲整個數組被重新出版每次添加一個新的記錄時間和 - 最有可能的 - 角2將每一次從頭開始重新構建整個列表。

由於這是一個很常見的情況,我想必須有更好的方法來做到這一點。

回答

2

是啊,肯定是 - 你需要使用flatmap

flatmap是去當你發現自己內的訂閱訂閱的方式。

你有一股流(一個元流),你需要壓扁它 - 然後你將能夠訂閱一次扁平流(避免嵌套訂閱)。

閱讀教程,直到它向您介紹flatmap的位。

https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

下面是一些代碼來踢你了......

public tagsTextStream = this.tagsTextSubject.asObservable().flatMap((q:string) => { 
// noinspection UnnecessaryLocalVariableJS 
let restStream = this.restQueryService.getTagsList(q) 
    .map((tags:any) => { 
    // filter out any tags that already exist on the document 
    let allTags = _.map(tags, 'name'); 
    let documentTags = _.map(this.tags, 'name'); 
    return _.pull(allTags, ...documentTags); 
    }) 
    .catch((err:any) => { 
    return Observable.throw(err); 
    }); 
return restStream; 
}).publish().refCount(); 

不要忘記...... .publish()引用計數()

或者你結束了多個請求和東西。

在我發送的鏈接上閱讀了更多關於它的全部內容。

PS

在上面的代碼中,q是從最初的可觀察到的被髮射的值。 請注意,術語observable和stream是可以互換的,它們是相同的。 observable只是描述一個你可以訂閱的流。因此,反應式編程(Rx)。您正在對來自該流的事件作出反應。