繁体   English   中英

从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的数据创建this.apiDayLabel

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函数

或者在这种情况下什么是最佳实践?

您可以在收到 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
   });
}

我建议您使用async await等待 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() createDay()

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() ngOnInit()

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

抱歉有任何错字。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM