J'ai le code suivant:
//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)
);
J'essaye de m'abonner à un résultat de 2 observables en utilisant forkJoin
.
Pour certaines raisons, le message "Données reçues" n'est pas affiché.
Mes variables userMeta
semblent bien dans console.log:
Qu'est-ce qui ne va pas?
Mise à jour: le code suivant ne renvoie rien non plus
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');
});
Ce que j'essaie de faire, c'est d'améliorer les performances du code suivant:
//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 => {
forkJoin()
nécessite que tous les observables source émettent au moins une fois et se terminent.
Cette démo suivante se termine comme prévu:
const source = forkJoin(
from([1,2,3]),
from([9,8,7,6])
).subscribe(
x => console.log('GOT:', x),
err => console.log('Error:', err),
() => console.log('Completed')
);
Démo en direct: https://stackblitz.com/edit/rxjs-urhkni
GOT: 3,6
Completed
Jan 2019: mis à jour pour RxJS 6
J'ai rencontré un problème similaire en utilisant Angular 2/Angularfire 2, en particulier lorsque je cherchais si les utilisateurs existaient par e-mail. Dans un cas, l'utilisateur existe et j'ai reçu un tableau d'un objet du Observable. Dans l'autre cas, l'utilisateur n'existait pas et j'ai reçu un tableau vide.
Lorsque j'ai utilisé forkJoin avec un resultSelector et un abonnement, ni le resultSelector ni la fonction d'abonnement n'ont jamais fonctionné. Cependant, quand j'ai essayé
Observable.Zip(
FirebaseListObservable,
FirebaseListObservable,
(...results) => {
return results.map(some code here)
}
).subscribe(res => console.log(res));
Le sélecteur et l'abonnement ont fonctionné. Je suppose que cela a à voir avec la réponse de @ martin, où forkJoin nécessite que les observables se terminent, car par définition, il renvoie les émissions les dernières. Si un observable ne se termine jamais, je suppose qu'il ne peut jamais avoir une émission last.
Peut-être que la liste des observables angularfire (ou des objets observables dans votre cas) n'est jamais complète, ce qui rend l'utilisation de forkJoin impossible. Heureusement, Zip a un comportement similaire et fonctionne toujours, la différence étant qu'il peut se répéter plusieurs fois si les données changent dans Firebase, alors que forkJoin ne combine que la dernière réponse.
Dans mon cas, j'examine 1) l'utilisation de Zip et j'accepte que mon code puisse s'exécuter plusieurs fois si les données utilisateur changent alors que le .Zip est toujours en cours d'exécution, 2) désactiver manuellement le Zip après le premier jeu de données, ou 3) abandonner Angularfire et essayer directement l'API Firebase, en utilisant quelque chose comme .once pour voir si je peux obtenir un observable qui complète et déclenche forkJoin.
J'ai rencontré un problème similaire: je créais une liste d'observables dynamiquement et j'ai remarqué que forkjoin()
n'émet jamais ni ne se termine si la liste des observables est vide tandis que Promise.all()
se résout avec une liste vide:
Observable.forkJoin([])
.subscribe(() => console.log('do something here')); // This is never called
La solution de contournement que j'ai trouvée consiste à vérifier la longueur de la liste et à ne pas utiliser cet opérateur lorsqu'il est vide.
return jobList.length ? Observable.forkJoin(jobList) : Observable.of([]);
Ajoutez simplement observer.complete ();
ne fonctionnera pas:
observer.next(...)
Fonctionnera:
observer.next(...);
observer.complete();
J'espère que cela aide.