簡體   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