how to build single object from 2 http requests in

2020-02-15 08:54发布

问题:

If you look at this question. the problem was really simple, but solutions were more complicated, to address more details I am asking this question.

If you look at stackblitz in service the code tries to build an object before passing it to a component. The problem I am having is the key value that is added by the code and it is breaking the formcontrols.

the first response returns object with routes that have only these values.

      addressPointId: "adress",
      municipalityId: "municipallyty",
      regionId: "regionId",
      settlementId: "settlementId",
      rvId: "rvId", // <---  not included in second call getAddressPoint 
      sequenceNumber: "sequenceNumber" // <---  not included in second call getAddressPoint 

the second http request takes these values and returns the it with name values, but excluding rvId and sequenceNumber.

    addressPointId: "adress",
    municipalityId: "municipallyty",
    regionId: "regionId",
    settlementId: "settlementId",
    regionName: "regionName", // <---  this is added 
    municipalityName: "municipalityName", // <---  this is added
    settlementName: "settlementName", // <---  this is added
    description: "description",

I want to get the result object.

{ <-- coming from first request getRequest
     "statusId": 1,
     "recDate": "2019-04-18T11:05:25.827Z",
     "requestVehicles": [
         {
             "garageId": 1,
             "routes": [
                 {
                     "addressPointId": "dasdad", // <-- is in both
                     "municipalityId": 34, // <-- is in both
                     "regionId": 4, // <-- is in both
                     "rvId": "",  // <-- coming from first request getRequest
                     "sequenceNumber": "", // <-- coming from first request getRequest
                     "settlementId": null, // <-- is in both
                     "regionName": "dasd", // <-- coming from second request getAddressPoint
                     "municipalityName": "dasdasd", // <-- coming from second request getAddressPoint
                     "settlementName": null, // <-- coming from second request getAddressPoint
                     "description": "Nadaburi" // <-- coming from second request getAddressPoint
                 } 
             ],
         }
     ],
 }

(unfortunately couldn't fix stackblitz) now I am getting this on my actual project:

{ <-- coming from first request getRequest
     "statusId": 1,
     "recDate": "2019-04-18T11:05:25.827Z",
     "requestVehicles": [
         {
             "garageId": 1,
             "routes": [
                 { // =================================
                     "key": { key object } // <========== this breaks the fromcontrols
//============================================================
                     "addressPointId": "dasdad", // <-- is in both
                     "municipalityId": 34, // <-- is in both
                     "regionId": 4, // <-- is in both
                     "rvId": "",  // <-- coming from first request getRequest
                     "sequenceNumber": "", // <-- coming from first request getRequest
                     "settlementId": null, // <-- is in both
                     "regionName": "dasd", // <-- coming from second request getAddressPoint
                     "municipalityName": "dasdasd", // <-- coming from second request getAddressPoint
                     "settlementName": null, // <-- coming from second request getAddressPoint
                     "description": "Nadaburi" // <-- coming from second request getAddressPoint
                 } 
             ],
         }
     ],
 }

the original code is coming from stackblitz.. I changed it fitting my actual scenario.

for some reason the new stackblitz isn't running, but it works fine for my actual project, other than extra key value in response.

回答1:

I think you can use RxJs combineLast to achieve what you want.

If you combine the result of the first call and the next call with combineLast will be able to subscribe and get both objects and return a combination of both of them.

Here's an example:

const objA = {xpto: 'xis'};
const objB = {moreData: 'pato'};


of(objA).pipe(
  map((a) => {
    return combineLatest(of(a), of(objB));
  })
).subscribe((result) => {
  result.pipe(
    map(([a, b]) => {
      return {
        newXpto: a.xpto,
        newMoreData: b.moreData
      };
    })
  ).subscribe((combinedObjects) => {
    console.log(combinedObjects);
   })
})

Something like this should work. I don't know if it is the more straigthfoward answer but I did it quickly. Nevertheless it gives you a sense of how you could do it.



回答2:

If I'm understanding your question correctly, it seems that you are asking about an http request that itself is dependent on another request and that the two requests together need to be combined in some way to create an object that you want to make use of. If I have that correct, then here are some workable examples.

first, you could just build the object you need in the call itself (i.e. in the component.ts file)

const id = this.getIdFromRoute(this.route, 'customerId');

let customerWithSource: ICustomer;

this.customerService.getById(id)
    .subscribe((customer) => {
        this.customerSourceService.getById(customer.SourceId)
            .subscribe((source) => {
                customerWithSource = customer;
                customerWithSource.CustomerSource = source;
            });
        });

or you could do this in the service, and that way in the component you are just subscribing to a method that already does all the work for you. Great if you are looking for reuse.

    getCustomerWithSource(id: number): Observable<ICustomer> {
        return this.getById(id).pipe(
            concatMap((customer) => {
                return this.customerSourceService
                    .getById(customer.SourceId)
                    .pipe(
                        map((source) => {
                            customer.CustomerSource = source;
                            return customer;
                        }),
                    );
            }),
        );
    }

the way this second one is working is that you are getting the first answer back, then using concatMap to make a second call using the values of the first call, then finally using map to make the final object and returning it.



标签: angular rxjs