Как объединить несколько запросов http и объединить результаты - PullRequest
0 голосов
/ 21 октября 2019

Мне нужно разобраться с ситуацией, когда у меня есть 3 конечных точки для вызова и я хочу получить данные наиболее удобным / эффективным способом. Первый вызов может быть обработан независимо и возвращает один результат. Вторая конечная точка возвращает коллекцию, но ей нужно будет инициировать 0- * последующие вызовы, где присутствует данный ключ.

В идеале хотелось бы получить коллекцию (из вызова 2-й конечной точки) как мутированную / новую коллекциюэто включает в себя результат 3-го вызова конечной точки.

В настоящее время я использую forkJoin (observableA $, observableB $) для обработки первых двух вызовов параллельно, но я не могу понять, как включить последовательные вызовы и получитьданные включены в observableB $

//Customer observable
const customer$ = this._customerManagementService.getCustomer(
  accountNumber
);
 return forkJoin({
      customer: customer$,
      saleCycles: saleCyclesWithVehicle$
    }).pipe(finalize(() => this._loaderFactoryService.hide()));
 getSalesWithVehicle(accountNumber: string, dealerKey: string) {
    return this._salesCycleService
      .getCyclesForCustomer({
        customerNumber: accountNumber,
        dealerKey: dealerKey
      })
      .pipe(
        concatMap((results: ISaleCycle[]) => {
          return results.map(cycle => {
            return this._purchaseVehicleService.getPurchaseVehicle(
              cycle.vehicleKey
            );
          });
        })
      );
  }

Я ожидаю, что коллекция будет включать дополнительные данные в качестве нового свойства в исходную коллекцию

ОБНОВЛЕНИЕ

Подумав еще немного, возможно, мне следует использовать снижение где-нибудь в решении. Таким образом я могу контролировать, что толкает массив, и он может быть динамическим?

  getSalesWithVehicle(accountNumber: string, dealerKey: string) {
    return this._salesCycleService
      .getCyclesForCustomer({
        customerNumber: accountNumber,
        dealerKey: dealerKey
      })
      .pipe(
        switchMap((results: ISaleCycle[]) => {
          return results.map(cycle => {
            if (cycle.vehicleKey) {
              return this._purchaseVehicleService
                .getPurchaseVehicle(cycle.vehicleKey)
                .pipe(
                  reduce((acc, vehicle) => {
                    return { cycle: cycle, vehicle: vehicle };
                  }, []),
                  toArray()
                );
            }
            else {
              ///No extra data to be had
            }
          });
        }),
        concatAll()
      );
  }

Ответы [ 2 ]

0 голосов
/ 28 октября 2019

Это решение, которое я в конце концов придумал. Я воспользовался советом от BoDeX и использовал concatMap (). В моем сознании было ясно, что я хочу использовать forkJoin и иметь возможность ссылаться на результаты по ключу объекта, т.е. customer или saleCycles.

В сценарии, где присутствует vehicleKey, мне нужно было вернуть результаты в видеопределенная структура данных, используя map (). Точно так же, если транспортное средство не было найдено, тогда мне просто нужно было наблюдать снаружи.

const customer$ = this._customerManagementService.getCustomer(accountNumber);

const saleCyclesWithVehicle$ = this.getSalesWithVehicle(accountNumber,dealerKey);

getSalesWithVehicle(accountNumber: string, dealerKey: string) {
    return this._salesCycleService
      .getCyclesForCustomer({
        customerNumber: accountNumber,
        dealerKey: dealerKey
      })
      .pipe(
        concatMap(cycles => {
          return from(cycles).pipe(
            concatMap((cycle: ISaleCycle) => {
              if (cycle.vehicleKey) {
                return this._purchaseVehicleService
                  .getPurchaseVehicle(cycle.vehicleKey)
                  .pipe(
                    map(vehicle => {
                      return { cycle: cycle, vehicle: vehicle };
                    })
                  );
              } else {
                return of({ cycle: cycle });
              }
            }),
            toArray()
          );
        })
      );
  }

return forkJoin({
      customer: customer$,
      saleCycles: saleCyclesWithVehicle$
    }).pipe(finalize(() => this._loaderFactoryService.hide()));
0 голосов
/ 22 октября 2019

Я бы использовал concatMap(), чтобы объединить ответы HTTP-запросов 2 и 3.

import { of } from 'rxjs'; 
import { map, concatMap } from 'rxjs/operators';

const pretendGetCustomer = of({accountNumber: 123, name:"John Doe"});

const pretendGetVehiculeHttpRequest = (customerNumber) => {
  return of([{custNum: 123, vehicleId:"2"}, {custNum: 123, vehicleId:"1"}]);
}
const pretendGetCyclesHttpRequest = (cycleIds) => {
  return of([{id:"1", name:"yellow bike", retailPrice:"$10"}, {id:"2", name:"red bike", retailPrice:"$20"}]);
}

const yourFunction = () => {
  pretendGetCustomer.subscribe(customer => {
    // Assuming you do other things here with cust, reason why we are subscribing to this separately
    // isHappy(customer)

    // Your second & third calls
    pretendGetVehiculeHttpRequest(customer.accountNumber).pipe(
      // Need to use concatMap() to subscribe to new stream
      // Note: use mergeMap() if you don't need the 1st stream to be completed
      //       before calling the rest
      concatMap(purchases => {
        const cyclesIds = purchases.map(p => p.vehicleId);
        // concatMap() requires an Observable in return
        return pretendGetCyclesHttpRequest(cyclesIds).pipe(
          // Use map() here because we just need to use the data,
          // don't need to subscribe to another stream
          map(cycles=>{
            // Retrun whatever object you need in your subscription
            return {
              customerNumber: customer.accountNumber,
              customerName: customer.name,
              purchases: purchases.map(p => cycles.find(c => p.vehicleId === c.id))
            }
          })
        );
      })
    ).subscribe(resultof2and3 => {
      // Do something with the new/mutated Object which is a result of
      // your HTTP calls #2 and #3
      console.log(resultof2and3);
    });
  });
}

yourFunction();

Я сделал стек, если вы хотите увидеть вышеописанный прогон (см. Консоль): https://stackblitz.com/edit/rxjs-nqi7f1

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...