質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

Promiseオブジェクトのthenの内側でChart.jsのグラフの初期値を代入してもグラフ表示が上手くいかない

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,759

score 13

 実行環境

  • Ionic2
  • Angular2

 詰まっていること

Ionic2上でグラフ表示にPromise利用せず、必要な初期値を与えると、Chart.jsのグラフ表示をすることが出来ました。
しかし、(SQLiteから初期データを取るときに)Promiseオブジェクトを作成して、thenの中でchart.jsの必要な初期値を設定すると、うまくグラフ描画がされません。

SQLiteからデータを取得してから描画させようとしているため、少し時間がかかるので、初期値が与えられる前にグラフの表示をしようとしてるからうまく動かないのかな?と思ってたりもするのですが...

 実際のコード

対象の関数はdisplayChart()です。

<chart [options]="options" [labels]="labels" [data]="datasets" type="line"></chart>
@Component({
  selector: 'game-score',
  templateUrl: 'game-score.html',
  providers: [ScoreService, ChartService, SQLService]
})
export class GameScoreComponent {
  gameSetting: any = {
    zeroone: {
      backgroundColor: 'rgba(255,99,132,0.2)',
      borderColor: 'rgba(255,99,132,1)',
      label: '01 GAMESのStats',
    },
    cricket: {
      backgroundColor: 'rgba(50, 82, 179, 0.2)',
      borderColor: 'rgba(50, 82, 179, 1)',
      label: 'CRICKETのStats',
    },
    countup: {
      backgroundColor: 'rgba(1, 110, 21, 0.2)',
      borderColor: 'rgba(1, 110, 21, 1)',
      label: 'COUNT-UPのStats',
    },
  }

  @Input() gameType: GameType

  // 子要素のchart情報を取得
  @ViewChild(ChartComponent) chart: ChartComponent

  /**
   * グラフ関連の変数
   */
  // グラフのx軸データ
  labels: string[] = []
  // グラフのデータ
  datasets: Chart.Dataset[] = []
  // グラフのオプション
  options: Chart.Options

  stats: number[] = []
  date: string[] = []

  constructor(
    public navCtrl: NavController,
    public platform: Platform,
    private scoreService: ScoreService,
    private chartService: ChartService,
    private sqlService: SQLService,
  ) {
  }

  /**
   * 初期処理
   */
  ngOnInit() {
    // グラフデータのセット
    this.displayChart()
  }

  /**
   * 表示形式が変更されたとき、グラフの再描画
   */
  onChange() {
    this.options.options.scales.xAxes[0].time.unit = this.unit
    this.chart.update()
  }

  /**
   * スコアをグラフ表示
   */
  async displayChart() {
    // SQLiteからデータ取得
    await this.sqlService.fetchStatsScore(this.gameType)
    .then((data: any) => {
      for(let i = 0; i < data.rows.length; i++){
        this.stats.push(parseInt(data.rows.item(i).stats))
        this.date.push(data.rows.item(i).created_at)
      }
    })
    .catch((error) => {
      alert(error)
    })
    // ここで初期値を設定してる・・・
    this.setChartData(this.stats, this.date)
  }


  /**
   * グラフのデータのセット
   * @param data 
   * @param labels 
   */
  setChartData(data: number[], labels: string[]) {
    this.labels = labels
    this.datasets = this.chartService.getDatasets(
      data,
      this.gameSetting[this.gameType].label,
      this.gameSetting[this.gameType].backgroundColor,
      this.gameSetting[this.gameType].borderColor
    )
    this.options = this.chartService.getOptions(this.gameType ,this.labels, this.datasets, this.unit, data)
  }
}

 やったこと

  • this.setChartData(this.stats, this.date)の後ろにthis.chart.update()でグラフの再描画を行ったがうまく行かなかった。
  • [追記]今はasync awaitで書いていますが,それより前のコードで,thenの中のfor文の後にsetChartDataを記述してもうまく行きませんでした.

 さいごに

どうかよろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

初期値設定をthis.date.pushの次の行で行ってはどうでしょうか?

  async displayChart() {
    // SQLiteからデータ取得
    await this.sqlService.fetchStatsScore(this.gameType)
    .then((data: any) => {
      for(let i = 0; i < data.rows.length; i++){
        this.stats.push(parseInt(data.rows.item(i).stats))
        this.date.push(data.rows.item(i).created_at)
        // ここで初期値を設定してる・・・
        this.setChartData(this.stats, this.date)
      }
    })
    .catch((error) => {
      alert(error)
    })
  }

promiseはそれが発行されたタイミングで即座に次の実行個所に移り、他の処理を実行します。
つまりthis.stats.pushとthis.date.pushが行われる前に、即座にthis.setChartDataが実行されています。そのタイミングでは当然this.statsとthis.dateは設定されていないためグラフは表示されません。
alert()等を用いて順次実行すると動きがよくわかると思います。

恐らく、上記コードでとりあえず動くのではないかと思いますが、試してみていただけますでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/04/23 19:08 編集

    外してたらすみません。基本的な確認ですが、thenは実行されていますか?またsetChatDataは実行されているでしょうか?console.logで確認済みであるような気はしますが・・・
    ---
    確認意図はPromiseのthenチェーンの中でresolveが呼び出されないケースがもしやあったりしないかということです。例えば最初のDBアクセス完了時にresolveを呼び出していないとか・・・

    キャンセル

  • 2017/04/23 19:10

    はい.alertで確認したところ,実行されていました...

    キャンセル

  • 2017/04/23 19:11

    そうでしたか。失礼しました。自分も再現させてみたかったのですがIonic2を入れられませんでした><

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る