0

My issue is that I'm getting data from three methods and then I want to load this data into a chart method but the chart method gets executed before the other methods complete (can't even get settimeout to work!!!) if you could give me some pointers I'd really appreciate it - thank you for your time

import {Injectable, OnDestroy, OnInit} from '@angular/core';
import { PeriodsService } from './periods.service';
import { OrdersChart, OrdersChartData } from '../data/orders-chart';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../../environments/environment';
import {Observable, Subject, throwError} from 'rxjs';
import {catchError, retry, takeUntil} from 'rxjs/operators';

@Injectable()
export class OrdersChartService extends OrdersChartData implements 
  OnInit, OnDestroy {
  private apiBase: string;
  private destroy$ = new Subject();

  private totalChartData: any = [];
  private day: any = [];
  private totalNoOfDocs: any = [];
  private failNoOfDocs: any = [];
  private sentNoOfDocs: any = [];

  private year = [
    '2012',
    '2013',
    '2014',
    '2015',
    '2016',
    '2017',
    '2018',
  ];

  private data = { };

  constructor(
    private period: PeriodsService,
  ) {
    super();
    this.apiBase = environment.serverEndpoint;
    this.loadTotalChartData();
  }

loadChartData() {
    // this.loadTotalChartData();
    // this.loadFailChartData();
    // this.loadSentChartData();
    // setTimeout(() => {
      this.data = {
        week: this.getDataForWeekPeriod(),
        month: this.getDataForMonthPeriod(),
        year: this.getDataForYearPeriod(),
      };
    // }, 2000);
  }


  private getDataForWeekPeriod(): { chartLabel: string[]; linesData: 
Observable<any>[] } {
    return {
      chartLabel: this.getDataLabels(7, this.period.getWeeks()),
      linesData: [
        this.totalNoOfDocs,
        this.failNoOfDocs,
        this.sentNoOfDocs,
      ],
    };
  }
  // Get lineChart data
  loadTotalChartData() {
const totalDoc$ = this.period.getTotalDocsDataWeek();
const failedDocs$ = this.period.getFailDocsDataWeek();
const sentDocs$ = this.period.getSentDocsDataWeek();

// totalDoc$.pipe(
combineLatest(totalDoc$, sentDocs$, failedDocs$, (total, sent, failed) => ({total, sent, failed}))
  // Observable.zip((totalDoc$, sentDocs$, failedDocs$, (total, sent, failed) => ({total, sent, failed}))
  // )
  .subscribe(pair => {
    // this.totalNoOfDocs = pair.total;
    // this.failChartData = data;
    for (let i = 0; i < Object.keys(pair.total).length; i++) {
      this.totalNoOfDocs.push( pair.total[i].numberOfDocuments + 15 );
    }
    // this.failChartData = data;
    for (let i = 0; i < Object.keys(pair.failed).length; i++) {
      this.failNoOfDocs.push( pair.failed[i].numberOfDocuments - 2 );
    }
    // this.sentChartData = data;
    for (let i = 0; i < Object.keys(pair.sent).length; i++) {
      this.sentNoOfDocs.push( pair.sent[i].numberOfDocuments + 5 );
    }
    // this.sentNoOfDocs = pair.sent;
    // this.failNoOfDocs = pair.failed;
    this.loadChartData();
  });
  }

  getDataLabels(nPoints: number, labelsArray: string[]): string[] {
    const labelsArrayLength = labelsArray.length;
    const step = Math.round(nPoints / labelsArrayLength);

    return Array.from(Array(nPoints)).map((item, index) => {
      const dataIndex = Math.round(index / step);

      return index % step === 0 ? labelsArray[dataIndex] : '';
    });
  }

  getOrdersChartData(period: string): OrdersChart {
    return this.data[period];
  }

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

**** PeriodService ****

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../../environments/environment';
import { Observable, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';

@Injectable()
export class PeriodsService {
  private apiBase: string;

  constructor(
    private http: HttpClient,
  ) {
    this.apiBase = environment.serverEndpoint;
  }


  getYears() {
    return [
      '2010', '2011', '2012',
      '2013', '2014', '2015',
      '2016', '2017', '2018',
    ];
  }

  getMonths() {
    return [
      'Jan', 'Feb', 'Mar',
      'Apr', 'May', 'Jun',
      'Jul', 'Aug', 'Sep',
      'Oct', 'Nov', 'Dec',
    ];
  }

  getWeeks() {
    return [
      'Mon',
      'Tue',
      'Wed',
      'Thu',
      'Fri',
      'Sat',
      'Sun',
    ];
  }

  // HttpClient API get() method => Fetch data list
  getSentDocsDataWeek(): Observable<any> {
    return this.http.get(this.apiBase + 'counters/lastWeek')
      .pipe(
        retry(1),
        catchError(this.handleError),
      );
  }

  getFailDocsDataWeek(): Observable<any> {
    return this.http.get(this.apiBase + 'counters/lastWeek')
      .pipe(
        retry(1),
        catchError(this.handleError),
      );
  }

  getTotalDocsDataWeek(): Observable<any> {
    return this.http.get(this.apiBase + 'counters/lastWeek')
      .pipe(
        retry(1),
        catchError(this.handleError),
      );
  }

  /*********************************************/

  getLinesChartDataMonth(): Observable<any> {
    return this.http.get(this.apiBase + 'counters/lastMonth')
      .pipe(
        retry(1),
        catchError(this.handleError),
      );
  }

  getLinesChartDataYear(): Observable<any> {
    return this.http.get(this.apiBase + 'counters/lastYear')
      .pipe(
        retry(1),
        catchError(this.handleError),
      );
  }

  // Error handling
  handleError(error) {
    let errorMessage = '';
    if (error.error instanceof ErrorEvent) {
      // Get client-side error
      errorMessage = error.error.message;
    } else {
      // Get server-side error
      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
    }
    window.alert(errorMessage);
    return throwError(errorMessage);
  }
}
tercou1
  • 113
  • 2
  • 11
  • **1.** Please don't attach an external link as the only code source. Provide it here as well. The question is unusable if the external link goes down. **2.** I see there are many failing imports in the Stackblitz. Eg. you seem to import a `PeriodsService`, but isn't defined. **3.** Refer here for quick intro to handling multiple co-dependent observables: https://stackoverflow.com/a/63685990/6513921 – ruth Jul 08 '21 at 09:10
  • @MichaelD question has been udated based on your comments – tercou1 Jul 08 '21 at 09:53
  • So basically you are asking how to wait for all Observables to be completed, before feeding the chart? – JSON Derulo Jul 08 '21 at 10:14
  • @JSONDerulo - yes exactly - i've tried different variations of async/await - promises and even setTimeout - but I didn't implement it correctly - if i set a breakpoint at this.loadSentChartData(); and then continue the data loads into the graph – tercou1 Jul 08 '21 at 10:23
  • @JSONDerulo - I tried to implement the combineLatest - see the original question where I have updated with my attempt but still can't get the data to load into the graph – tercou1 Jul 08 '21 at 15:28

0 Answers0