2016-09-01 12 views
5

Załóżmy, że chcę pobrać zestaw rekordów ze sklepu, wyświetlić je na liście, używając *ngFor, np.Jak zbudować prawdziwą obserwowalną kolekcję za pomocą RxJS i Angular2?

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

Teraz użytkownik kliknie „” ... Nowy przycisk, kolejny rekord jest dodawany do sklepu i

recordAdded: EventEmitter<string>; 

pożary mi powiedzieć o lokalizacji. Dostaję tę nową płytę - i tylko ten zapis - ze sklepu i ... okrzyki, jak mogę uzyskać mój *ngFor, aby wyświetlić ten dodatkowy rekord?

Ok, więc mogę zachować wszystkie rekordy w tablicy, na przykład

_records: Record[]; 

i wypełnić tę tablicę poprzez zapisanie się na Observable<Record[]> jak

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

Ale ta tablica musi być sama Observable w celu powiadamiania konsumentów, gdy pojawi się nowy rekord. Więc

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

Uch ... Nie tylko jest to rozdzierający patrzeć, istnieje również mnóstwo napowietrznych jak cała tablica zostanie ponownie opublikowany za każdym razem nowy rekord jest dodawany i - najprawdopodobniej - kątowa 2 będzie odtwarzaj całą listę od zera na każdym kroku.

Ponieważ jest to taki powszechny scenariusz, wyobrażam sobie, że musi być o wiele lepszy sposób na zrobienie tego.

Odpowiedz

2

Tak, tam na pewno jest - trzeba użyć flatmap

flatmap jest do zrobienia, gdy znajdziesz się subskrybowania W ciągu subskrybować.

Masz strumień strumieni (metastream) i musisz go spłaszczyć - wtedy będziesz mógł zasubskrybować jeden raz do spłaszczonego strumienia (unikając zagnieżdżonego subskrybowania).

Przeczytaj samouczek do momentu, w którym wprowadzi cię do płaskiej mapy.

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

Oto niektóre kodu kopnąć cię ...

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(); 

Nie zapomnij ... .publish(). RefCount()

lub skończyć z wiele próśb i rzeczy.

przeczytaj więcej o tym wszystkim na linku, który wysłałem.

PS

W kodzie powyżej, q oznacza wartości są emitowane z początkowej widoczne. Należy pamiętać, że terminy obserwowalne i strumienie są wymienne, są to te same rzeczy. obserwowalne to po prostu opis strumienia, który można subskrybować. Stąd programowanie reaktywne (Rx). Reagujesz na wydarzenia pochodzące ze strumienia.