Enthu
Enthu

Reputation: 532

How to make subsequent calls using rxjs

At three places I am making API calls (I have numbered it (1),(2),(3)).

getCMPortsMapping(siteRef: string) {

  Object.keys(cmBoardPortsEnum).forEach(port => {

    let queryParams = "output and system and enabled and config and " + cmBoardPortsEnum[port];

    let cmBoardPortsMappings = new CMBoardPortsMappings("", "", false, "", "");
    // ------- (1) --------
    this.siteService.getDetailsBySiteRef(queryParams, siteRef).subscribe(portsDetail => {
      if (portsDetail && portsDetail.rows.length > 0) {
        cmBoardPortsMappings.type = cmBoardPortsEnum[port];

        //Check if port is enabled ------ (2) --------
        this.siteService.getWritablePointData(this.helperService.parseRef(portsDetail.rows[0].id)).subscribe(portEnable => {
          if (portEnable && portEnable.rows.length) {
            //got data for port
            if (portEnable.rows[0] && portEnable.rows[0].val) {
              //got port enable/disbale
              let val = this.helperService.TypeMapping(portEnable.rows[0].val)
              switch (val) {
                case "1.0":
                  cmBoardPortsMappings.isEnabled = true;
                  //Get the port mapping
                  let mappingQuery = "system and cmd and " + cmBoardPortsEnum[port];
                  // ----------- (3) -----------
                  this.siteService.getDetailsBySiteRef(mappingQuery, siteRef).subscribe(mappingDetails => {
                    if (mappingDetails && mappingDetails.rows.length) {
                      mappingDetails.rows[0].dis.split("SystemEquip-")[1] != "" ? cmBoardPortsMappings.mapping = mappingDetails.rows[0].dis.split("SystemEquip-")[1] : '';
                      this.helperService.parseRef(mappingDetails.rows[0].id) != "" ? cmBoardPortsMappings.ref = this.helperService.parseRef(mappingDetails.rows[0].id) : '';

                      if (cmBoardPortsMappings.mapping != "") {
                        cmBoardPortsMappings.param = cmBoardPortsMappings.mapping.toLowerCase().replace(/\s/g, "")
                      }
                    }
                    else {
                      throw new Error("In correct port mapping read from haystack")
                    }
                  });
                  break;
                case "0.0":
                  cmBoardPortsMappings.isEnabled = false;
                  cmBoardPortsMappings.mapping = "";
                  break;
                default:
                  throw new Error("In correct port val read from haystack")
              }
              this.cmBoardPortsMappingsCollection.set(cmBoardPortsEnum[port], cmBoardPortsMappings);
            }
          }
        });
      }
    });
  });
}

I had used switchmap in some other piece of code as well

this.siteService.getFloorRooms(this.floorRef).pipe(
  switchMap(res => {
    const rest = res
    let elementId = [];
    res.rows.forEach((element) => {
      elementId.push(element.id)
    });
    for (const color of elementId) {
      this.roomref = (color).split(":")[1].split(" ")[0];
    }
    return this.siteService.checkPairedRooms(this.roomref)
  })
).subscribe(m => {
  this.rooms = m.rows;
  if (m.rows.length == 1) {
    this.paired = true;
  }
  this.getExistingFloorPlan();
});

Should I use mergemap, concatmap, switchmap? What is the correct way to implement it? As pointed out by someone foreach inside switchmap will not return , so using forkjoin and other utilities would help but I haven't used these rxjs utility functions.

Upvotes: 0

Views: 80

Answers (1)

frido
frido

Reputation: 14099

It doesn't matter whether you use mergemap, concatmap, switchmap with http requests, because they only emit once and complete.

Create an array of concatenated http requests mapping each request to the next one and the final one to your desired output. Then pass that array to forkJoin. Enjoy.

getCMPortsMapping(siteRef: string) {
  forkJoin(Object.keys(cmBoardPortsEnum).map(port => {
    let queryParams = "output and system and enabled and config and " + cmBoardPortsEnum[port];
    return this.siteService.getDetailsBySiteRef(queryParams, siteRef).pipe(
      filter(portsDetail => portsDetail && portsDetail.rows.length > 0),
      switchMap(portsDetail => this.siteService.getWritablePointData(this.helperService.parseRef(portsDetail.rows[0].id))),
      filter(portEnable => portEnable && portEnable.rows.length && portEnable.rows[0] && portEnable.rows[0].val),
      switchMap(portEnable => {
        const cmBoardPortsMappings = new CMBoardPortsMappings("", "", false, "", "");
        cmBoardPortsMappings.type = cmBoardPortsEnum[port];
        const val = this.helperService.TypeMapping(portEnable.rows[0].val)
        switch (val) {
          case "1.0":
            cmBoardPortsMappings.isEnabled = true;
            return enrichCmBoardPortsMappings(cmBoardPortsMappings, siteRef);
          case "0.0":
            cmBoardPortsMappings.isEnabled = false;
            cmBoardPortsMappings.mapping = "";
            return of(cmBoardPortsMappings);
          default:
            return throwError('In correct port val read from haystack');
        }
      })
    )
  })).subscribe(cmBoardPortsMappingsArray => cmBoardPortsMappingsArray.forEach(cmBoardPortsMappings =>
    this.cmBoardPortsMappingsCollection.set(cmBoardPortsMappings.type, cmBoardPortsMappings)
  ));
}

enrichCmBoardPortsMappings(cmBoardPortsMappings: CMBoardPortsMappings, siteRef: string): Observable<CMBoardPortsMappings> {
  let mappingQuery = "system and cmd and " + cmBoardPortsMappings.type;
  return this.siteService.getDetailsBySiteRef(mappingQuery, siteRef).pipe(
    tap(mappingDetails => { 
      if(!(mappingDetails && mappingDetails.rows.length)) throw new Error('In correct port mapping read from haystack') ;
    }),
    map(mappingDetails => {
      if (mappingDetails.rows[0].dis.split("SystemEquip-")[1] != "") {
        cmBoardPortsMappings.mapping = mappingDetails.rows[0].dis.split("SystemEquip-")[1];
      }
      if (this.helperService.parseRef(mappingDetails.rows[0].id) != "") {
        cmBoardPortsMappings.ref = this.helperService.parseRef(mappingDetails.rows[0].id);
      }
      if (cmBoardPortsMappings.mapping != "") {
        cmBoardPortsMappings.param = cmBoardPortsMappings.mapping.toLowerCase().replace(/\s/g, "")
      }
      return cmBoardPortsMappings;
    })
  )
}

Upvotes: 1

Related Questions