2016-11-02 4 views
1

Как я могу каскадировать вызовы RxJs для извлечения данных из этой надуманной службы.Каскадные вызовы ajax с RxJs

Первый запрос идет к/клиент/1

/клиент /: идентификатор

Ответ:

{ 
    Name: "Tom", 
    Invoices: [1,3], 
    Orders: [5,6] 
} 

В ответ клиента есть 2 InvoiceIds, которые мы используем, чтобы получить доступ к второй услуги:

/счета-фактуры /: id

Response

{ 
    Id: 1, 
    Amount: 10 
} 

В ответ клиента есть 2 OrderIds, которые мы используем для доступа к третьей службы:

/заказов /: идентификатор

Response

{ 
    Id:2, 
    Date: '2016-11-12'   
} 

В конце я хотел бы поиграть с объектом выглядит следующим образом:

{ 
    Name: "Tom", 
    Invoices: [ 
    { 
     Id: 1, 
     Amount: 10 
    }, 
    { 
     Id: 3, 
     Amount: 5 
    }], 
    Orders: [ 
    { 
    Id:5, 
    Date: '2016-11-12'   
    }, 
    { 
    Id:6, 
    Date: '2016-11-12'   
    }] 
} 

Как передать идентификаторы по конвейеру, чтобы получить зависимые объекты.

Чувство моего чувства говорит мне, что я, вероятно, должен использовать оператор flatMap, но я абсолютно не знаю, как все это может работать вместе.

var ajax = Rx.DOM.getJSON('/api/customers/1') 
    .flatMap(p => p.Invoices.map(x => 
     Rx.DOM.getJSON('/api/invoices/' + x) 
     )); 
+0

'Rx', вероятно, не является правильным инструментом для работы здесь. Используйте Promises и 'fetch()'. –

ответ

1

Это типичный вариант использования, где вам нужно построить ответ из нескольких вызовов HTTP:

const Observable = Rx.Observable; 

var customerObs = Observable.create(observer => { 
    Observable.of({Name: "Tom", Invoices: [1,3], Orders: [5,6]}) 
     .subscribe(response => { 
      var result = { 
       Name: response.Name, 
       Invoices: [], 
       Orders: [], 
      }; 

      let invoicesObs = Observable.from(response.Invoices) 
       .flatMap(id => Observable.of({ Id: Math.round(Math.random() * 50), Amount: Math.round(Math.random() * 500) }).delay(500)) 
       .toArray(); 

      let ordersObs = Observable.from(response.Orders) 
       .flatMap(id => Observable.of({ Id: Math.round(Math.random() * 50), Amount: Math.round(Math.random() * 500) }).delay(400)) 
       .toArray(); 

      Observable.forkJoin(invoicesObs, ordersObs).subscribe(responses => { 
       result.Invoices = responses[0]; 
       result.Orders = responses[1]; 

       observer.next(result); 
      }); 

     }); 
}); 

customerObs.subscribe(customer => console.log(customer)); 

Посмотреть демо: https://jsfiddle.net/martinsikora/uc1246cx/

Я использую Observable.of() для моделирования HTTP-запросы, flatMap(), чтобы перевести каждый идентификатор счета/заказа в наблюдаемый (другой HTTP-запрос), который повторно используется, а затем toArray() для сбора всех значений, испускаемых из цепочки операторов, и их повторного использования в одном массиве (просто потому, что это удобно).

Оператор forkJoin() ждет, пока весь источник данных не будет заполнен, а затем испустит их последнее значение в виде массива (поэтому мы собираем массив массивов в responses).

См аналогичный вопрос: Performing advanced http requests in rxjs

+0

Это очень близко. Я заменил вызовы Observable.Of с соответствующими вызовами Rx.DOM.getJSON ('/ api/orders /' + id). CustomerObs.subscribe разрешает быстрее, чем сетевые вызовы getJSON. Таким образом, при запуске console.log Заказы и Invoces все еще пусты. Нужно ли мне как-то присоединиться к ним? – Marius

+1

@ Marius Ах, ты прав! В идеале с 'forkJoin()', см. Мой обновленный ответ. – martin

+0

Отлично, теперь все работает так, как ожидалось. – Marius

Смежные вопросы