2016-10-28 2 views
7

У меня есть следующий код: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) 
); 

Я пытаюсь подписаться на результат 2 наблюдаемых с помощью forkJoin.

По некоторым причинам сообщение «Данные получены» не отображается.

Мои 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 => { 
+0

'forkJoin()' испускает значение после того, как оба Observables завершены, так что вы уверены, что они делают? Возможно, один из них заканчивается ошибкой ... – martin

+1

Ошибок нет (см. Вопрос). Они также должны работать, потому что прежний код был подпиской внутри подписки, и он работал – TheUnreal

+0

'forkJoin()' не пропускает ошибки из исходных Observables, поэтому это ничего не печатает, даже если оно вызывает ошибки. Если вы хотите убедиться, что он не испускает ошибок, вам необходимо подписаться на каждую из исходных наблюдаемых. – martin

ответ

6

forkJoin()требует как Наблюдаемые для завершения.

Нижеследующая демо завершается, как и ожидалось:

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

Смотреть демо: http://plnkr.co/edit/MtYfGLgqgHACPswFTVJ5?p=preview

GOT: 3,6 
Completed 
+0

Вы проверили мой обновленный код в конце вопроса? потому что он работает с одними и теми же наблюдаемыми, просто не работает 'forkJoin()'. Это действительно странно ... – TheUnreal

+0

@ TheUnreal Но это не то же самое, что вы хотите делать с 'forkJoin()'. '.subscribe ((roleData) => {...' испускает значение при каждом вызове 'next'.' forkJoin() '. ** forkJoin() требует, чтобы оба Observables завершались. ** в противном случае это не испускает ничего – martin

+0

Ну, похоже, что я пропустил использование 'forkJoin()'. Поскольку ваш ответ corrcet, я его одобрю - и откройте новый вопрос о моем случае – TheUnreal

10

У меня была аналогичная проблема с использованием Угловое 2/Angularfire 2, в частности, где я смотрела ли пользователей существует по электронной почте. В одном случае пользователь существует, и я получил массив из одного объекта из Observable. В другом случае пользователь не существовал, и я получил пустой массив.

Когда я использовал forkJoin с resultSelector и подпиской, ни функция выбора, ни функция подписки никогда не работали. Однако, когда я попробовал

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

И селектор, и подписка работали. Я предполагаю, что это связано с ответом @ Martin, где forkJoin требует, чтобы наблюдаемые были завершены, потому что по определению он возвращает последние излучений. Если наблюдаемый никогда не завершится, я полагаю, что он никогда не может иметь последний эмиссии.

Возможно, наблюдаемые наблюдательные знаки (или объектные наблюдаемые в вашем случае) никогда не завершатся, что делает невозможным использование forkJoin. К счастью, zip имеет аналогичное поведение и по-прежнему работает, причем разница заключается в том, что он может повторяться несколько раз, если данные изменяются в Firebase, где forkJoin объединяет только последний ответ.

В моем случае я смотрю либо 1), используя zip, и принимая, что мой код может выполняться несколько раз, если пользовательские данные изменяются, пока .zip все еще работает, 2) вручную отключает zip после первого набора данные возвращаются или 3) вырезать Angularfire и попробовать Firebase api напрямую, используя что-то вроде .once, чтобы увидеть, могу ли я получить наблюдаемое, которое завершает и запускает forkJoin.

+1

У меня была точно такая же проблема, которую можно было бы довольно легко исправить, используя 'Observable.combineLatest' вместо' Observable.forkJoin'. Кредиты переходят на https://github.com/angular/angularfire2/issues/617 – djnose

6

Я столкнулся с аналогичной проблемой: я создавал список наблюдаемых динамически, и я заметил, что forkjoin() никогда не излучает и не завершается, если список наблюдаемых пуст, тогда как Promise.all() решает с пустым списком:

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

Обходной путь, который я нашел, - проверить длину списка и не использовать этот оператор, когда он пуст.

return jobList.length ? Observable.forkJoin(jobList) : Observable.of([]); 
Смежные вопросы