web-dev-qa-db-ja.com

Observable.forkJoin()は実行されません

私は次のコードを持っています:

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

forkJoinを使用して2つのオブザーバブルの結果をサブスクライブしようとしています。

何らかの理由で、「Data received」メッセージは表示されません。

userMeta変数はconsole.logで正常に見えます:

enter image description here

どうしましたか?

更新:次のコードも何も返しません

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

私が実際にやろうとしているのは、次のコードのパフォーマンスを改善することです。

//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() は、すべてのソースObservablesが少なくとも1回発行して完了することを要求します。

この次のデモは期待どおりに完了します。

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

ライブデモ: https://stackblitz.com/edit/rxjs-urhkni

GOT: 3,6
Completed

2019年1月:RxJS 6用に更新

16
martin

Angular 2/Angularfire 2を使用して同様の問題が発生しました。具体的には、ユーザーがメールで存在したかどうかを調べていました。1つのケースでは、ユーザーが存在し、1つのオブジェクトの配列を観察可能:他の場合、ユーザーは存在せず、空の配列を受け取りました。

ResultSelectorとsubscribeでforkJoinを使用した場合、resultSelectorもsubscribe関数も実行されませんでした。しかし、私が試したとき

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

セレクターとサブスクライブの両方が機能しました。これは@martinの答えと関係があると思います。定義では、forkJoinがオブザーバブルを完了する必要があるのは、定義により最後の放出を返すためです。オブザーバブルが完全に完了しない場合、lastの放出が発生することはないと思います。

おそらく、アンギュラファイアリストのオブザーバブル(または、あなたの場合はオブジェクトオブザーバブル)は決して完了せず、forkJoinの使用は不可能です。幸いなことに、Zipにはsimilarの動作があり、動作します。Firebaseでデータが変更された場合、forkJoinが最後の応答のみを結合する場合、数回繰り返すことができる点が異なります。

私の場合、1)Zipを使用して、.Zipの実行中にユーザーデータが変更されるとコードが複数回実行される可能性があることを受け入れています。2)最初のデータセットが返された後、Zipを手動で無効にします。 3)Angularfireを捨て、.onceのようなものを使用して直接Firebase apiを試して、forkJoinを完了してトリガーするオブザーバブルを取得できるかどうかを確認します。

12
ansorensen

私は同様の問題に直面しました:オブザーバブルのリストを動的に作成していましたが、オブザーバブルのリストが空の場合、forkjoin()は空になっても解決されず、Promise.all()リスト:

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

私が見つけた回避策は、リストの長さをチェックし、空の場合はこの演算子を使用しないことです。

return jobList.length ? Observable.forkJoin(jobList) : Observable.of([]);
12
bgondy

Observer.complete();を追加するだけです。

動作しません:

observer.next(...)

動作します:

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

それが役に立てば幸い。

4
Itay Ben Shmuel