angulartypescriptangular-httpclientangular-httpangular-http-interceptors

How to return value outside subscribe Angular


Template

<div class="row" *ngFor="let otc of this.jsonData;index as j">
        <div>
            <table class="table table-striped table-fixed">
             
    <tr *ngFor="let opc of this.winServiceInfo(j);index as i">
 

Typescript

ngOnInit(): void {
    this.geWinService();
  }

 
 winServiceInfo(j: number) {
    this.winServiceURL = JSON.parse(this.WinService[j].windowsServicesInfo)["Stactuscheck"];
    this.dataArrs = [];
    this.service.getWinServicesInfo(this.winServiceURL)
      .pipe(
        catchError(this.handleError)
      )
      .subscribe(
        (data: any) => {
          this.setSubscribeData(data);
          console.log(this.dataArrs);
          return this.dataArrs;
        });
    console.log(this.dataArrs);
    return this.dataArrs;
  }

setSubscribeData(data): any {
    this.WinService = data.windowsServicesInfo;
    this.dataArrs = this.getKeyValJsonObj();
    return this.dataArrs;
  }

getKeyValJsonObj() {
    this.dataArr = [];
    for (let key of this.sliceIntoChunks()) {
      for (let i in key) {
        this.dataArr.push({ 'key': i, 'value': key[i] });
      }
    }
    return this.dataArr;
  }

On method winServiceInfo first console.log(this.dataArrs) retuens Arrar(3) but the second console.log(this.dataArrs) returns Arrar(0). I understand that subscribe is an asynchronous operation and for that reason.

So how to handle the situation to return the Array(3) from second console.log(this.dataArrs)


Solution

  • First off, NEVER use a function call like this in HTML.

    At every change detection, the function will be ran. Not only this is a huge performance issue, but if you also make HTTP calls, you can ruin someone's data plan in seconds.

    Second, try to avoid using this like you do. Constrain your variables to the scope of where they're used.

    Instead, make an observable to observe :

    
    data$ = forkJoin(
      this.jsonData.map(j => {
        const winServiceURL = JSON
          .parse(this.WinService[j].windowsServicesInfo)["Stactuscheck"];
    
        return this.service.getWinServicesInfo(this.winServiceURL);
      }).pipe(
        switchMap(data => {
          const WinService = data.windowsServicesInfo;
          const dataArr = [];
          for (let key of this.sliceIntoChunks()) {
            for (let i in key) {
              dataArr.push({ 'key': i, 'value': key[i] });
            }
          }
          return dataArr;
        })
      )
    )
    
    

    In your HTML

    <div class="row" *ngFor="let opc of data$ | async">
      {{ opc | json }}
    </div>