2016-10-28 3 views
7

Ich habe den folgenden Code:Observable.forkJoin() nicht ausführt, nicht

//Loop: For each user ID/Role ID, get the data 
userMeta.forEach((businessRole) => { 
    Observable.forkJoin(
    af.database.object('/roles/'+businessRole.$value), 
    af.database.object('/users/'+businessRole.$key) 
).subscribe(
    data => { 
     console.log("Data received"); 
     data[1].role = data[0]; 
     this.users.push(data[1]); 
    }, 
    err => console.error(err) 
); 

ich zu einem Ergebnis von 2 Observablen versuche mit forkJoin zu abonnieren.

Aus einigen Gründen wird die Meldung "Daten empfangen" nicht angezeigt.

Meine userMeta Variablen betrachtet console.log fein:

enter image description here

Was ist los?

Update: der folgende Code nichts zurückgibt entweder

let source = Observable.forkJoin(
     af.database.object('/roles/'+businessRole.$value), 
     af.database.object('/users/'+businessRole.$key) 
    ); 
    let subscription = source.subscribe(
     function (x) { 
    console.log("GOT: " + x); 
    }, 
    function (err) { 
    console.log('Error: %s', err); 
    }, 
    function() { 
    console.log('Completed'); 
    }); 

Was ich eigentlich zu tun versuchen, ist die Leistung des folgenden Codes verbessern:

//Subscription 3: role ID to role Name 
     af.database.object('/roles/'+businessRole.$value) 
     .subscribe((roleData) => { 
     //Subscription 4: Get user info 
     af.database.object('/users/'+businessRole.$key).subscribe(user => { 
+0

'forkJoin()' gibt einen Wert aus, nachdem beide Observables vollständig sind, also sind Sie sicher, dass sie es tun? Vielleicht endet einer von ihnen mit einem Fehler ... – martin

+1

Auch keine Fehler (siehe Frage Update). Sie müssen auch arbeiten, weil der frühere Code ein subscribe in einem subscribe war, und es funktionierte – TheUnreal

+0

'forkJoin()' übergibt keine Fehler von Quell-Observables, so dass dies nichts drucken wird, selbst wenn es Fehler warf. Wenn Sie sicherstellen möchten, dass keine Fehler auftreten, müssen Sie die einzelnen Observables abonnieren. – martin

Antwort

6

forkJoin()erfordert beide Observablen zu vervollständigen.

Die folgende Demo beendet wie erwartet:

let source = Observable.forkJoin(
    Observable.from([1,2,3]), 
    Observable.from([9,8,7,6]) 
); 
let subscription = source.subscribe(
    function (x) { 
     console.log("GOT: " + x); 
    }, 
    function (err) { 
     console.log('Error: %s', err); 
    }, 
    function() { 
     console.log('Completed'); 
    }); 

Live-Demo Siehe: http://plnkr.co/edit/MtYfGLgqgHACPswFTVJ5?p=preview

GOT: 3,6 
Completed 
+0

Haben Sie meinen aktualisierten Code am Ende der Frage überprüft? weil es mit den gleichen Observablen funktioniert, arbeite einfach nicht 'forkJoin()'. Es ist wirklich seltsam ... – TheUnreal

+0

@TheUnreal Aber das ist nicht das selbe was du mit 'forkJoin()' machen willst. '.subscribe ((roleData) => {...} gibt bei jedem' nächsten' Aufruf einen Wert aus. 'forkJoin()'. ** forkJoin() benötigt beide Observables. ** sonst gibt es nichts aus – martin

+0

Nun, es scheint, als ob ich '' forkJoin() '' '' '' '' missverwendet. Weil Ihre Antwort richtig ist, werde ich es genehmigen - und eine neue Frage über meinen Fall öffnen. – TheUnreal

10

hatte ich ein ähnliches Problem Angular mit 2/Angularfire 2, speziell wo ich oben, ob Nutzer, bestand per E-Mail. In einem Fall existiert der Benutzer und ich habe ein Array von einem Objekt vom Observable erhalten. Im anderen Fall existierte der Benutzer nicht und ich erhielt ein leeres Array.

Wenn ich forkJoin mit einem resultSelector und einem subscribe verwendet habe, wurde weder der resultSelector noch die subscribe-Funktion ausgeführt. Jedoch, als ich versuchte

Observable.zip(
    FirebaseListObservable, 
    FirebaseListObservable, 
    (...results) => { 
    return results.map(some code here) 
    } 
).subscribe(res => console.log(res)); 

Sowohl der Selektor als auch das Abonnement funktionierte. Ich nehme an, dies hat mit @ Martins Antwort zu tun, wo ForkJoin die Observablen benötigt, um abzuschließen, weil per Definition die die letzten Emissionen zurückgibt. Wenn ein Observable nie abgeschlossen wird, nehme ich an, dass es niemals eine letzte Emission haben kann.

Vielleicht werden die angularfire-Listen-Observablen (oder Objektobservablen in Ihrem Fall) niemals vollständig, was die Verwendung von forkJoin unmöglich macht. Glücklicherweise hat zip ähnlich Verhalten und funktioniert immer noch, mit dem Unterschied, dass es mehrere Male wiederholen kann, wenn die Daten in Firebase ändert, wo wie ForkJoin nur die letzte Antwort kombiniert.

In meinem Fall sehe ich entweder 1) mit zip und akzeptiere, dass mein Code mehrmals ausgeführt wird, wenn sich Benutzerdaten ändern, während die Zip noch läuft, 2) manuell deaktivieren Sie die Zip nach dem ersten Satz von Daten zurück, oder 3) Graben Angularfire und versuchen Sie die Firebase API direkt, mit etwas wie .once, um zu sehen, ob ich eine Observable erhalten kann, die beendet und löst ForkJoin.

+1

Ich hatte genau das gleiche Problem, das recht einfach mit 'Observable.combineLatest' anstelle von' Observable.forkJoin' behoben werden konnte. Credits gehen zu https://github.com/angular/angularfire2/issues/617 – djnose

6

Ich habe ein ähnliches Problem konfrontiert: Ich war dynamisch eine Liste von Observablen zu schaffen, und ich habe bemerkt, dass forkjoin() aussendet nie noch vervollständigt, wenn die Liste von Observablen leer ist, während Promise.all() mit einer leeren Liste löst:

Observable.forkJoin([]) 
    .subscribe(() => console.log('do something here')); // This is never called 

Die Problemumgehung, die ich gefunden habe, besteht darin, die Länge der Liste zu überprüfen und diesen Operator nicht zu verwenden, wenn er leer ist.

return jobList.length ? Observable.forkJoin(jobList) : Observable.of([]); 
Verwandte Themen