Home > Blockchain >  A typescript subscribe collects data from API and writes that into an array, but I can only output o
A typescript subscribe collects data from API and writes that into an array, but I can only output o

Time:09-16

I am getting data from an API like this:

ngAfterViewInit() {
  this.exampleDatabase = new ExampleHttpDatabase(this._httpClient);
  var href = '/schuhe-store/status';

  if (environment.production === false) {
    href = 'https://sales.dailysshop.com/schuhe-store/status';
  }

  for (var val of this.dataArray) {
    const requestUrl = `${href}?type=${val}`;

    this._httpClient
      .get<StatusInterface>(requestUrl)
      .pipe(
        map((data) => {
          return data;
        })
      )
      .subscribe(
        (data) => {
          this.dataResults[val] = data;
          console.log(this.dataResults[val]);
        },
        (error) => {
          const dialogConfig = new MatDialogConfig();

          if (error.status == 404) {
            dialogConfig.disableClose = true;
            dialogConfig.autoFocus = true;
            console.log(error.errno);
            this.dialog.open(DialogOverviewExampleDialog, dialogConfig);
          } else if ((error.status = 200)) {
            this.dialog.open(DialogOverviewExampleDialog, dialogConfig);
          }
          this.routeNotRegistered = true;
        }
      );
  }
}

In my HTML I am outputting 4 lines as follows:

            <mat-list-item>
                <mat-icon mat-list-icon>done</mat-icon>
                <div mat-line>Cronjob</div>
                <div mat-line *ngIf='getTimestamp("cron"); else loading;'>Zuletzt beendet: {{ getTimestamp("cron") | date:'dd.MM.yyyy HH:mm" }} Uhr</div>
            </mat-list-item>
            <mat-list-item>
                <mat-icon mat-list-icon>done</mat-icon>
                <div mat-line>Exportprozess</div>
                <div mat-line *ngIf='getTimestamp("export"); else loading;'>Zuletzt beendet: {{ getTimestamp("export") | date:"dd.MM.yyyy HH:mm" }} Uhr</div>
            </mat-list-item>
            <mat-list-item>
                <mat-icon mat-list-icon>done</mat-icon>
                <div mat-line>Deltaexport</div>
                <div mat-line *ngIf='getTimestamp("delta"); else loading;'>Zuletzt beendet: {{ getTimestamp("delta") | date:"dd.MM.yyyy HH:mm" }} Uhr</div>
            </mat-list-item>
            <mat-list-item>
                <mat-icon mat-list-icon>error</mat-icon>
                <div mat-line>Importprozess</div>
                <div mat-line *ngIf='getTimestamp("import"); else loading;'>Zuletzt beendet: {{ getTimestamp("import") | date:"dd.MM.yyyy HH:mm" }} Uhr</div>
            </mat-list-item>

The getTimestamp is the following code:

    getTimestamp(key: string):number|undefined{
        if (this.dataResults[key] && this.dataResults[key]["timestamp"] !== undefined)
            return (this.dataResults[key]["timestamp"]);
        return (undefined);
    }

In my HTML only one value is outputted, currently, only the getTimestamp("delta") and I don't know, how to get all 4 values.

Can someone point this out and deliver a solution?

Kind regards Henning

CodePudding user response:

Instead of subscribing to the sub observables (HTTP calls) directly, you can use RxJS forkJoin to combine all of them, and emit the result through subscribe method once all the sub observables have been completed.

Try the following:

ngAfterViewInit() {
  this.exampleDatabase = new ExampleHttpDatabase(this._httpClient);
  var href = '/schuhe-store/status';

  if (environment.production === false) {
    href = 'https://sales.dailysshop.com/schuhe-store/status';
  }

  if (!this.dataArray?.length) return;

  forkJoin(
    this.dataArray.map((val) => {
      const requestUrl = `${href}?type=${val}`;
      return this._httpClient.get<StatusInterface>(requestUrl).pipe(
        tap((data) => {
          this.dataResults[val] = data;
        })
      );
    })
  ).subscribe(
    () => {
      console.log('DONE!');
    },
    (error) => {
      const dialogConfig = new MatDialogConfig();

      if (error.status == 404) {
        dialogConfig.disableClose = true;
        dialogConfig.autoFocus = true;
        console.log(error.errno);
        this.dialog.open(DialogOverviewExampleDialog, dialogConfig);
      } else if ((error.status = 200)) {
        this.dialog.open(DialogOverviewExampleDialog, dialogConfig);
      }
      this.routeNotRegistered = true;
    }
  );
}

CodePudding user response:

const dataArray = ['cron', 'import', 'export', 'delta'];


from(dataArray)
  .pipe(
concatMap((type) => {
  const requestUrl = `${href}?type=${type}`;
    return this._httpClient.get<StatusInterface>(requestUrl).pipe(map((data) => ({ [type]: data })))
  }
),
    scan((acc, curr) => ({...acc, ...curr}), {})// value will come one by one, if you want to get final result (full object) you can replace scan with reduce operator
  )
  .subscribe((data) => {
    console.log(data); // {cron: StatusInterface, import: StatusInterface, ...}
    this.dataResults = data;
  }, 
  error => {});
  • Related