2017-02-20 26 views
0

Я нашел много примеров, описывающих, как несколько наблюдаемых вызовов могут быть объединены в один вызов Observable, но из того, что я нашел, эти вызовы всегда принимают по крайней мере одно из следующего:Угловое объединение двух (похожих) наблюдаемых

1: количество вызовов известно 2: фиксировано количество вызовов 3: вызовы представляют собой разные объекты, объединенные в один. (как в arg1 => call1, arg2 => call2)

Но я не нашел никакой достойной информации о том, как обрабатывать комбинацию Observables, когда эти вызовы выполняются динамически или когда вместо сопоставления результатов с разными переменные, вы хотите расширить список, который вы пытаетесь собрать.

Предоставить прецедент, в котором это применимо: пользователь может подписаться на несколько «групп» продуктов. Каждая группа связана с идентификатором, который используется для извлечения продуктов из удаленного сервиса. Группа должна получить все продукты из всех групп, объединить их и отобразить их пользователю.

Наиболее логичным решением для меня является ожидание завершения всех вызовов при сборе результатов в другом списке, и оттуда было бы легко скомпилировать эти списки в единый желаемый результат, но у меня есть не смог найти способ эффективно достичь этого. И любопытно услышать, могут ли другие идеи о том, как лучше всего решить эту проблему.

let responses = Array<Observable<Articles>> 
    for (let id of subscriptions) { 
     let response = this.http.get(producturl + id, headers).map(
      //insert mapping... 
     ); 
    responses.push(response); 
} 

здесь я попытался использовать .merge(), чтобы попытаться объединить «ответы» вместе, но чувствую, что я не достаточно знакомы с командой/злоупотребляя его. Я также пробовал перебирать Observables и подписываться на них по очереди, но это кажется субоптимальным и не дает желаемых результатов. Я пробовал больше, но эти два варианта кажутся мне наиболее вероятными, чтобы быть на правильном пути к правильному решению ... Если требуется больше кода, чтобы увидеть, где может возникнуть потенциальная проблема, я с удовольствием поделился бы тем, И спасибо за любой ввод.

ответ

0

Вы можете использовать forkJoin вместе с нормальным reduce:

let responses: Array<Observable<Articles>> = []; 
for (let id of subscriptions) { 
    let response: Observable<Articles> = this.http.get(producturl + id, headers).map(); 
    responses.push(response); 
} 

Observable.forkJoin(responses) 
    .map(response => response.reduce((a,b) => {return a.concat(b)})) 
    .subscribe((response: Articles[]) => { 
     console.log(response); 
     //output is a flat array of all Articles 
}); 

Не забудьте добавить оператор rxjs:

import 'rxjs/add/observable/forkJoin'; 
+0

Эй Пьер. Спасибо за ответ. Я нашел несколько примеров, используя forkJoin, но не нашел документально подобным. Кажется, это именно то, что мне нужно! Всего две ноты: вы пропустили «)» в конце карты, а concat не является нативной функцией. Не оказалось нужным, хотя я предполагаю, что это метод, чтобы убедиться, что списки, которые вы объединяете, не имеют дубликатов? –

+0

Я уверен, что пропустил это ')': D, никаких кодовых подсказок в полях ответа stackoverflow. [concat] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/concat) является встроенной функцией массива, хотя :). Вместе с уменьшением он гарантирует, что двумерный массив становится одномерным. Пока нет проверки дубликатов, хотя – PierreDuc

+0

Да, я видел, в чем проблема. Уменьшение ответа предполагает, что вы получаете один объект результата, который не является массивом, а единственным объектом «статьи», где оператор concat невозможен , Это можно исправить, убедившись, что вы получите список из него. Итак, в этом случае Array >> Не пытаясь отвлечься от вашей помощи, я благодарен. Просто пытаюсь сделать уверен, что любые потенциальные будущие посетители этой темы не оставляют удивляться, почему код, похоже, не работает. :) –