从 api 获取数据后创建 Chart.js

create Chart.js after getting data from api

我在 Angular 中有两个函数:

从 Web 服务获取一些数据并将其存储在 this.apiDaythis.apiDayLabel 变量中:

getDayScan() {
    this.btcPriceService.getDailyBTCScan().subscribe(data => {
      data.Data.Data.forEach(price => {
        this.apiDay.push(price.open);
        this.apiDayLabel.push(new Date(price.time * 1000).toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'}));
      });
    });
}

和一个用 this.apiDaythis.apiDayLabel 中的数据创建一个 chartjs :

public createDay(defaultChartConfig: any) {

    this.canvas = document.getElementById('dayChart');
    this.ctx = this.canvas.getContext('2d');

    const dataTotal = {
      // Total Shipments
      labels: this.apiDayLabel,
      datasets: [{
        label: 'Price',
        fill: true,
        backgroundColor: this.bgColorSelector(this.apiDay),
        borderColor: this.borderColorSelector(this.apiDay),
        borderWidth: 2,
        borderDash: [],
        borderDashOffset: 0.0,
        pointBackgroundColor: this.borderColorSelector(this.apiDay),
        pointBorderColor: 'rgba(255,255,255,0)',
        pointHoverBackgroundColor: this.borderColorSelector(this.apiDay),
        pointBorderWidth: 20,
        pointHoverRadius: 4,
        pointHoverBorderWidth: 15,
        pointRadius: 0,
        data: this.apiDay,
      }]
    };

    this.myChartDay = new Chart(this.ctx, {
      type: 'lineWithLine',
      data: dataTotal,
      options: defaultChartConfig
    });
  }

我在ngOnInit()函数中这样调用这两个函数:

ngOnInit() {
    this.getDayScan();
    this.createDay(defaultChartConfig);
}

我的问题是图表是在我从 api 获得数据之前创建的。

有没有办法等待数据到达那里然后开始创建图表?

像这样(伪代码)

public createDay(defaultChartConfig: any) {

    getDayScan();

    // wait for it to finish so every necessary variable is declared
    // and only THEN go on with the other code 

    this.canvas = document.getElementById('dayChart');
    this.ctx = this.canvas.getContext('2d');

    ...

}

所以我只需要调用 ngOnInit

中的 createDay 函数

或者在这种情况下最佳做法是什么?

建议您使用asyncawait等待api回复

 async getDayScan() {
        await this.btcPriceService.getDailyBTCScan().subscribe(data => {
          data.Data.Data.forEach(price => {
            this.apiDay.push(price.open);
            this.apiDayLabel.push(new Date(price.time * 1000).toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'}));
          });
        });
    }

createDay()

调用 getDayScan()
public async createDay(defaultChartConfig: any) {

    await getDayScan();

    // wait for it to finish so every necessary variable is declared
    // and only THEN go on with the other code 

    this.canvas = document.getElementById('dayChart');
    this.ctx = this.canvas.getContext('2d');

    ...

}

您只需要从 ngOnInit()

调用 createDay()

如果您不喜欢使用异步等待,请使用 this 工作示例。

对于任何打字错误,我们深表歉意。

得到API的回复后即可填写图表数据。

创建一个通用函数供多个同时调用。

getJoin(URL_Array: Array<string>): Observable<any> {
    const observableBatch = [];
    URL_Array.forEach((url) => {
      observableBatch.push(this._httpClient.get<any>(`${API_URL}${url}`)
        .pipe(map(res => { return res; })));
    });
    return forkJoin(observableBatch);
};


getDayScan() {
  const urls = [
     this.btcPriceService.getDailyBTCScan1(), // API 1 URL
     this.btcPriceService.getDailyBTCScan2()  // API 2 URL
  ];
    this.btcPriceService.getJoin(urls)
     .subscribe(res => {
        // You will get array inside res with the same number of the array that you passed API. So Use for loop for res.

        for (let i = 0; i < res.length; i++) { // here will be res.length is 2 in this example
            const element = res[i];

            // Apply your logic here if you got different response in different API
            element.Data.Data.forEach(price => {
               this.apiDay.push(price.open);
               this.apiDayLabel.push(new Date(price.time * 1000)
               .toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'}));
            });
        }

        // Call chart function after loop complete
        this.createDay(defaultChartConfig);            
    });
}

createDay(defaultChartConfig: any) {
   this.canvas = document.getElementById('dayChart');
   this.ctx = this.canvas.getContext('2d');

   const dataTotal = {
     // Total Shipments
     labels: this.apiDayLabel,
     datasets: [{
       label: 'Price',
       fill: true,
       backgroundColor: this.bgColorSelector(this.apiDay),
       borderColor: this.borderColorSelector(this.apiDay),
       borderWidth: 2,
       borderDash: [],
       borderDashOffset: 0.0,
       pointBackgroundColor: this.borderColorSelector(this.apiDay),
       pointBorderColor: 'rgba(255,255,255,0)',
       pointHoverBackgroundColor: this.borderColorSelector(this.apiDay),
       pointBorderWidth: 20,
       pointHoverRadius: 4,
       pointHoverBorderWidth: 15,
       pointRadius: 0,
       data: this.apiDay,
    }]
  };

  this.myChartDay = new Chart(this.ctx, {
     type: 'lineWithLine',
     data: dataTotal,
     options: defaultChartConfig
   });
}