2016-12-10 7 views
1

Ich Abonnieren eines BehaviorSubjectroutes$, die ein Array von RichtungenObservable Iteration vollständige Ereignis

emittiert z.B. ['left', 'top', 'left']

Dann möchte ich jedes Element dieses Arrays mit 200ms Verzögerung protokollieren, jetzt nachdem alle Elemente protokolliert wurden, möchte ich route finished protokollieren.

Ich versuchte das komplette Ereignis ()=>{} und finally() Operator, aber sie beide nicht feuern, da routes$ noch am Leben ist und neue Richtungen ausgibt.

/** Stream recent directions */ 
this.route$.switchMap(() => { 
    return Observable 
    .interval(200) 
    .timeInterval() 
    .take(this.route$.getValue().length) 
}).subscribe(
    (v) => { 
    if (v.value === this.route$.getValue().length) return; 
    let i = v.value; 
    this.moveStep(this.route$.getValue()[i]); 
    } 
); 

Derzeit verwende ich diese Abhilfe

.subscribe(
    (v) => { 
    if (v.value === this.route$.getValue().length) return; 
    let i = v.value; 
    this.moveStep(this.route$.getValue()[i]); 

    /** Check if it is the last iteration */ 
    if(i + 1 === this.route$.getValue().length){ 
     console.log('route finished'); 
     this.state = PlayerState.Idle; 
    } 
    } 
); 

Gibt es eine native Möglichkeit, dies in beobachtbar zu erreichen?

+0

Können Sie dies für Klarheit umschreiben? – Asti

Antwort

2

Wenn ich das, was Sie versuchen, richtig verstehe, möchten Sie einen Wert ausgeben, wenn das an das BehaviorSubject übergebene Array vollständig iteriert wurde und Sie nur den letzten Wert erhalten möchten.

Versuchen Sie, .getValue() direkt aus der Observable-Kette zu vermeiden, da der Inhalt von .getValue() etwas ist, mit dem Sie bereits in der Kette arbeiten sollten.

var routes$ = new BehaviorSubject(['default']); 

routes$.switchMap((arr) => { 
    return Observable.interval(200) 
     .take(arr.length) 
     .map(i => arr[i]) 
     .timeInterval() 
     .do(null, null,() => console.log('Complete')); 
}).subscribe(value => { 
    console.log(value); 
}); 

routes$.next(['left', 'top', 'left']); 

setTimeout(() => { 
    routes$.next(['top', 'right', 'down']); 
}, 1000); 

Diese Drucke zu trösten:

TimeInterval { value: 'left', interval: 208 } 
TimeInterval { value: 'top', interval: 241 } 
TimeInterval { value: 'left', interval: 207 } 
Complete 
TimeInterval { value: 'top', interval: 204 } 
TimeInterval { value: 'right', interval: 200 } 
TimeInterval { value: 'down', interval: 205 } 
Complete 

Siehe Live-Demo: https://jsbin.com/muxasa/5/edit?js,console

Beachten Sie, dass die ['default'] nie da switchMap() ein neues Array empfängt zurückemittiertes wird, wenn routes$.next(['left', 'top', 'left']);

+0

Ich möchte jedes Element in 200ms Verzögerung nicht nur die letzte protokollieren, aber ich möchte eine Aktion auslösen, wenn diese Elemente protokolliert werden. (nachdem es über das Array iteriert hat). Ihre jsbin protokolliert nur den letzten Wert –

+0

'.do' funktioniert, aber jetzt werden alle Elemente auf einmal protokolliert, kann ich 200ms Verzögerung zwischen ihnen behalten? –

+0

Danke Mann, ich suchte nach dem "do" -Operator –

0

Aufruf Wenn Ihr Observable ist noch nicht abgeschlossen. Sie können debounce() verwenden, um auf ein Zertifikat zu warten eine Menge Zeit, bevor Sie etwas tun. Andere Optionen wären buffer Ihre Werte nach Zeit/Betrag und dann nach dem Auslösen des Puffers etwas tun.