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

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

新規登録して質問してみよう
ただいま回答率
85.50%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

1回答

2207閲覧

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

ferretdayo

総合スコア13

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2017/04/22 16:37

編集2022/01/12 10:55

実行環境

  • Ionic2
  • Angular2

詰まっていること

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

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

実際のコード

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

html

1<chart [options]="options" [labels]="labels" [data]="datasets" type="line"></chart>

javascript

1 2@Component({ 3 selector: 'game-score', 4 templateUrl: 'game-score.html', 5 providers: [ScoreService, ChartService, SQLService] 6}) 7export class GameScoreComponent { 8 gameSetting: any = { 9 zeroone: { 10 backgroundColor: 'rgba(255,99,132,0.2)', 11 borderColor: 'rgba(255,99,132,1)', 12 label: '01 GAMESのStats', 13 }, 14 cricket: { 15 backgroundColor: 'rgba(50, 82, 179, 0.2)', 16 borderColor: 'rgba(50, 82, 179, 1)', 17 label: 'CRICKETのStats', 18 }, 19 countup: { 20 backgroundColor: 'rgba(1, 110, 21, 0.2)', 21 borderColor: 'rgba(1, 110, 21, 1)', 22 label: 'COUNT-UPのStats', 23 }, 24 } 25 26 @Input() gameType: GameType 27 28 // 子要素のchart情報を取得 29 @ViewChild(ChartComponent) chart: ChartComponent 30 31 /** 32 * グラフ関連の変数 33 */ 34 // グラフのx軸データ 35 labels: string[] = [] 36 // グラフのデータ 37 datasets: Chart.Dataset[] = [] 38 // グラフのオプション 39 options: Chart.Options 40 41 stats: number[] = [] 42 date: string[] = [] 43 44 constructor( 45 public navCtrl: NavController, 46 public platform: Platform, 47 private scoreService: ScoreService, 48 private chartService: ChartService, 49 private sqlService: SQLService, 50 ) { 51 } 52 53 /** 54 * 初期処理 55 */ 56 ngOnInit() { 57 // グラフデータのセット 58 this.displayChart() 59 } 60 61 /** 62 * 表示形式が変更されたとき、グラフの再描画 63 */ 64 onChange() { 65 this.options.options.scales.xAxes[0].time.unit = this.unit 66 this.chart.update() 67 } 68 69 /** 70 * スコアをグラフ表示 71 */ 72 async displayChart() { 73 // SQLiteからデータ取得 74 await this.sqlService.fetchStatsScore(this.gameType) 75 .then((data: any) => { 76 for(let i = 0; i < data.rows.length; i++){ 77 this.stats.push(parseInt(data.rows.item(i).stats)) 78 this.date.push(data.rows.item(i).created_at) 79 } 80 }) 81 .catch((error) => { 82 alert(error) 83 }) 84 // ここで初期値を設定してる・・・ 85 this.setChartData(this.stats, this.date) 86 } 87 88 89 /** 90 * グラフのデータのセット 91 * @param data 92 * @param labels 93 */ 94 setChartData(data: number[], labels: string[]) { 95 this.labels = labels 96 this.datasets = this.chartService.getDatasets( 97 data, 98 this.gameSetting[this.gameType].label, 99 this.gameSetting[this.gameType].backgroundColor, 100 this.gameSetting[this.gameType].borderColor 101 ) 102 this.options = this.chartService.getOptions(this.gameType ,this.labels, this.datasets, this.unit, data) 103 } 104}

やったこと

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

さいごに

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

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

JavaScript

1 async displayChart() { 2 // SQLiteからデータ取得 3 await this.sqlService.fetchStatsScore(this.gameType) 4 .then((data: any) => { 5 for(let i = 0; i < data.rows.length; i++){ 6 this.stats.push(parseInt(data.rows.item(i).stats)) 7 this.date.push(data.rows.item(i).created_at) 8 // ここで初期値を設定してる・・・ 9 this.setChartData(this.stats, this.date) 10 } 11 }) 12 .catch((error) => { 13 alert(error) 14 }) 15 }

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

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

投稿2017/04/23 00:03

akabee

総合スコア1947

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ferretdayo

2017/04/23 02:42

回答ありがとうございます. 実際に教えていただいた通り,then((data) => { //処理 })の処理の中でデータのセットをしたのですが,やはり動かないようです... また,一応aync awaitで順序通り上からしたの順で動くようにしているので,順序では大丈夫そうです
KSwordOfHaste

2017/04/23 02:49

質問者さんはasync関数の中で、「awaitを使ってfetchStatsScoreからthenに至るPromiseの完了を待ってからsetChartDataさせることを意図している」と思います。上記では1行データをセットする度に(全ての行のデータが揃わないうちに)setCharDataする結果になるためそれは意図とは違うことになる気がするのですがいかがでしょうか?
akabee

2017/04/23 02:57 編集

ferretdayoさん、KSwordOfHasteさん、async、awaitについて不勉強であり申し訳ありません。実行を待ってくれるのですね。しかも繰り返し処理も入っていたようで・・。全然ダメでしたね。ほかの可能性を検討してみます。
ferretdayo

2017/04/23 03:00

返信ありがとうございます. コードの品質が悪いため誤解を生んでしまったようで申し訳ありません. setChartData関数は設定したいデータの配列を渡す感じで作っているので,意図しているのは 「全てのstats情報とdate情報を全て配列に入れたのち,setChartDataに”全てのstats情報を含む配列”と”全てのdate情報を含む配列”を与えてデータのセットをする.」 という意図で書いています. KSwordOfHasteさんの考えている意図と食い違いあったら申し訳ありません.
akabee

2017/04/23 03:02

全面的に私の間違いですので、コードの品質には問題ないと思います。
KSwordOfHaste

2017/04/23 03:31

>ferretdayoさん その意図どおりに受け取りました。恥ずかしながら自分はIonic2、Angular2いずれも未知なのでJSの勉強させてもらおうと本件を覗き見してる状態です...
akabee

2017/04/23 06:51

机上でコードを確認していますが全く問題点が見えてこないですね。。。 私がコードを書いているとしたら試すのは以下2点ですが、試行済みでしょうか。 1.this.setChartData(this.stats, this.date)の直前でthis.statsとthis.dateの値を表示すると、値が入っているか 2.this.setChartData(this.stats, this.date)の直前でthis.statsとthis.dateの値を直接指定した場合にグラフは正常に表示されるか 要するにthis.sqlService.fetchStatsScoreのresponseの受け取り方が間違っていないかという基本的なところを確認したいです。 1,2ともに問題ない(1で値が入っているにもかかわらずグラフが表示されない、かつ2の方法で値を代入すればグラフは問題なく表示される)のであれば、問題は複雑です。
ferretdayo

2017/04/23 09:39

返信ありがとうございます. 1.の場合ですが,それぞれちゃんと入っているんですよね・・・ 2.の場合ですが,thenの中で初期値を直接指定した(this.statsではなく,[10,3,2,4]のような値の)場合もグラフ表示されなかった.
akabee

2017/04/23 09:48

2.について、thenの中ではなく例えばthis.setChartData([10,3,2,4], [a,b,c,d])だと動くのですか? 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) }) alert(this.stats);//1.の確認 alert(this.date);//1.の確認 // ここで初期値を設定してる・・・ this.setChartData([10,3,2,4], [a,b,c,d]);//2.の確認 }
ferretdayo

2017/04/23 09:48

補足ですが, Promiseの外側 で初期値を入力した場合では,グラフ表示が出来たんですよね. SQLiteから取得している時間が微妙にかかっており,その時間で描画がうまく行っていないのかな...と あとからデータ取得した場合のchart.jsの初期値設定方法が間違っているのかもしれないのかな...と思っています^;
akabee

2017/04/23 09:54

外側で指定すれば上手くいっているのですか。ではthen内部のthisが別のものを指してしまっているのかもしれませんね。 机上で確認した限りでは問題ないように見えましたが、アロー関数の書き方が間違っているのでしょうか・・・。 個人的にもあまり好きな書き方ではないのですが、以下のようにthat = thisを用いてみてはどうでしょうか。 async displayChart() { // SQLiteからデータ取得 var that = this; await this.sqlService.fetchStatsScore(this.gameType) .then(function(data: any){ for(let i = 0; i < data.rows.length; i++){ that.stats.push(parseInt(data.rows.item(i).stats)) that.date.push(data.rows.item(i).created_at) } }) .catch((error) => { alert(error) }) // ここで初期値を設定してる・・・ this.setChartData(that.stats, that.date) }
ferretdayo

2017/04/23 09:54

async await で Promiseの処理を待っている場合は, 2. でもグラフ描画はされない状態です. async await を無くし,Promiseの外(2.の場所)でthis.setChartDataを呼ぶとグラぐ描画がされます.
ferretdayo

2017/04/23 09:56

外側で指定すればうまく行っているのは,async awaitを消した場合です. awaitしている状態だとグラフ描画されないです^;
ferretdayo

2017/04/23 09:56

ちなみに,var that = this;でも,一回動かしたことがあるのですが,うまく行かない状態でした...
akabee

2017/04/23 10:04 編集

外側で値を直接指定しても、async awaitのままだとグラフ表示されないのですか?であれば、async awaitに問題があることは確定ですね。 最初勘違いでコメントし、あまり詳しくないながらコメントを続けてみましたが、再現環境も無く、そもそもasync await自体にも不勉強ですので、ちょっと私ではこれ以上お力になれそうにありません。申し訳ありません。
ferretdayo

2017/04/23 10:06

いえいえ,回答していただいて凄くありがたかったです. akabeeさん貴重なお時間に回答していただいてありがとうございました. 引き続き原因を探していきたいと思います!
KSwordOfHaste

2017/04/23 10:10 編集

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

2017/04/23 10:10

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

2017/04/23 10:11

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問