2016-09-01 27 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)。您正在对来自该流的事件作出反应。