web-dev-qa-db-fra.com

Observable.forkJoin () ne s'exécute pas

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:

enter image description here

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 => {
14
TheUnreal

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

16
martin

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.

12
ansorensen

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([]);
12
bgondy

Ajoutez simplement observer.complete ();

ne fonctionnera pas:

observer.next(...)

Fonctionnera:

observer.next(...);
observer.complete();

J'espère que cela aide.

4
Itay Ben Shmuel