javascriptangularrxjsobservablefork-join

Angular - Using mergeMap to fetch data from 2 APIs and saving them in an Array


Scenario : On ngOnInit, I need to call 3 APIs, Fork-Join them and save data in an array. 1st API is independent. 2nd is also independent but the 3rd one depends on response of the 2nd API.

I have not worked with forkjoin or mergemap before and I am a bit confused.

What's happening :

I have created a common method which takes an identifier to figure out which endpoint to hit and the object with required parameters and then there is response and error handling.

Service File :

  callMethod(str, obj, cb?) {
    return new Observable(observer => {
      this.httpService.getHttpParams(this.URLS_CONSTANT[str], obj, res => {
        observer.next(res.data.content ? res.data.content : res.data);
        observer.complete();
      }, err => { })
    })

  }

So, I am able to fetch the response from all 3 APIs but the final result after fork-join contains the response of 1st and 3rd api. the response of 2nd is missing, and I dont know what is going on.

This is the method I wrote:


  fetchAllData() {
    let inp = this.input_row;


    let response1 = this.service.callMethod('rate_plan', { companyId: inp.cpnyId, servAbbr: inp.servAbbr, productNumber: inp.prdctNo, orgNumber: inp.orgNo, rateCategory: inp.rateCat, ratePlanNumber: inp.ratePlanNo });

    let response2 = this.service.callMethod('approve_rate', { prodctNo: inp.prdctNo, servAbbr: inp.servAbbr, companyId: inp.cpnyId, ratePlanNo: inp.ratePlanNo }).pipe(map(item => {
        this.approveRate = item
        let appRate = item[0]
        return appRate
      }), mergeMap(data => this.service.callMethod('rate_detail', { companyId: inp.cpnyId, ratePlanNo: inp.ratePlanNo, rateCaseGrpngNo: data['rateCaseGrpngNo']})) )

      forkJoin([response1, response2]).subscribe(x => console.log(x))
  }

}

The final console has values of response from API call 1 and 3. What change is required to create an array with three separate objects. Let me know if any more clarification is required.


Solution

  • Your approach is perfect, but the second response can be run through a switchMap to get the third response, then run over a map, to return the individual values of secondResponse and thirdResponse inside an array!

    fetchAllData() {
        let inp = this.input_row;
    
        let response1 = this.service.callMethod('rate_plan', {
            companyId: inp.cpnyId,
            servAbbr: inp.servAbbr,
            productNumber: inp.prdctNo,
            orgNumber: inp.orgNo,
            rateCategory: inp.rateCat,
            ratePlanNumber: inp.ratePlanNo,
        });
    
        let response2 = this.service
            .callMethod('approve_rate', {
                prodctNo: inp.prdctNo,
                servAbbr: inp.servAbbr,
                companyId: inp.cpnyId,
                ratePlanNo: inp.ratePlanNo,
            })
            .pipe(
                switchMap(responsesecond => {
                    this.approveRate = responsesecond;
                    let appRate = responsesecond[0];
                    return this.service
                        .callMethod('rate_detail', {
                            companyId: inp.cpnyId,
                            ratePlanNo: inp.ratePlanNo,
                            rateCaseGrpngNo: responsesecond['rateCaseGrpngNo'],
                        })
                        .pipe(
                            map(responsethird => {
                                return [responsesecond, responsethird];
                            })
                        );
                })
            );
    
        forkJoin([response1, response2]).subscribe(x => console.log(x));
    }