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

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

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

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

3回答

7318閲覧

async、await内の変数をグローバル変数のように使い回したい

kazamidori2140

総合スコア9

JavaScript

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

2クリップ

投稿2020/08/25 12:49

実現したいこと

クイズのデータをAPIで取得し、勉強としてクイズアプリを作成しています。

ソースコードにある変数「quizData」を他の関数でも使いたいので、グローバル変数のように扱いたいです。

試したこと1

クイズのデータが格納されている「quizData」をreturnしました。

JavaScript

1const callApi = async () => { 2 const res = await fetch('https://opentdb.com/api.php?amount=10&type=multiple'); 3 const quizData = await res.json(); 4 return quizData.results 5} 6callApi(); 7console.log(callApi()); 8```上記を実行すると、コンソールに以下が実行されました。 9![イメージ説明](8de07238fc77108f69bd07d7b881f1f0.png) 10「PromiseValue」から値を持ってくることができず断念しました。 11 12## 試したこと2 13クイズのデータを関数外の配列である、変数「arr」に追加すれば使えるのではと考えました。 14```JavaScript 15let arr = []; 16 17const callApi = async () => { 18 const res = await fetch('https://opentdb.com/api.php?amount=10&type=multiple'); 19 const quizData = await res.json(); 20 for (i = 0; i < quizData.results.length; i++) { 21 arr.push(quizData.results[i]); 22 } 23} 24callApi(); 25console.log(arr); 26```上記を実行すると、コンソールに以下が実行されました。 27![イメージ説明](69bc2261df2567e7a55b87d3639995a5.png) 28なぜか配列に追加されず、クイズデータを扱えなかった。 29 30## 何が原因だと考えるか 31私の非同期処理やAPIの扱い方の理解が足りていないのが原因だと考えます。 32 33どのようにすれば、クイズデータを他の関数などにも使い回すことができるでしょうか。 34 35よろしくお願いします。

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

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

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

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

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

guest

回答3

0

ベストアンサー

試したこと2の方向でやってみました。

html

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>Document</title> 7</head> 8<body> 9 <div id="quiz"></div> 10 <script> 11 let arr = []; 12 13 async function callApi() { 14 const res = await fetch('https://opentdb.com/api.php?amount=10&type=multiple'); 15 const quizData = await res.json(); 16 for (i = 0; i < quizData.results.length; i++) { 17 arr.push(quizData.results[i]); 18 } 19 } 20 21 window.onload = async function() { 22 await callApi(); 23 console.log("arr", arr); 24 25 const quizDiv = document.getElementById('quiz'); 26 arr.forEach(quiz => { 27 const div = document.createElement("div"); 28 div.innerHTML = quiz.question; 29 quizDiv.append(div); 30 }); 31 }; 32 </script> 33</body> 34</html>

投稿2020/08/25 13:17

YakumoSaki

総合スコア2027

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

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

kazamidori2140

2020/08/25 13:33

ご回答ありがとうございます。 そして、わざわざコードまで書いてくださりありがとうございます!
guest

0

どのようにすれば、クイズデータを他の関数などにも使い回すことができるでしょうか。

2つ方法が考えられます。

  • 「試したこと2」のパターンで、非同期的にロードが終わってから(callApi();の次の行では取れません)arrを参照する
  • 得られたPromisePromiseのまま活用する

投稿2020/08/25 12:55

maisumakun

総合スコア145121

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

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

maisumakun

2020/08/25 12:58

ということで、「どのタイミングで」値をとって使うか、ということも考える必要があります。
kazamidori2140

2020/08/25 13:23

ご回答ありがとうございます。 前者の「試したこと2」のパターンで試してみようと思います。
guest

0

試してないので全然ダメだったら申し訳ありません。
代入する変数を先にグローバルで定義していてもムリですか?

let quizData; const callApi = async () => { const res = await fetch('https://opentdb.com/api.php?amount=10&type=multiple'); quizData = res.json(); return quizData.results }

投稿2020/08/25 13:29

H40831

総合スコア973

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

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

kazamidori2140

2020/08/25 13:38

ご回答ありがとうございます。 試したみましたが、「undefined」になりますね。
H40831

2020/08/25 13:47

ちなみに、非同期処理の const res = await fetch('https.... が完了しているタイミングで表示していますか? (完了していなかったら undefined になるのは当たり前なので)
kazamidori2140

2020/08/26 01:43

すみません。 完了しているタイミングでの表示の仕方が分からないんですよ〜 それができれば、正解にグッと近づけるんですけど...
H40831

2020/08/26 02:11 編集

そうですよね。 同期処理は非同期処理よりさっさと進んでしまうので、値を取得してくるより前に実行されてしまいます。 なので、非同期処理で取得してくる値をグローバルで使いたいというのは、 それ自体が複雑な要件なのだとまずは認識していただき、どういうタイミングで後続の処理をさせるべきなのかを前もって言語化しておくことが大切だと思います。 (グローバルで res を使う場合、それ以降の処理は、すべて res が代入するまで待たされることになるが、いいのか?などです) で、完了しているタイミングでの表示といっても状況によって適切な方法は違うと思いますが、 const res = fetch('https://... のように、値を取得してくる時点では await をつけず、 resの値を使いたいタイミングで const res = await res; のようにawaitをつけると、 const res という代入処理の実行を await res が完了するまで待ってくれます。 なので、後続の処理も確実に const res が代入されたあとに実行されます。
kazamidori2140

2020/08/26 05:47

懇切丁寧なご回答ありがとうございます。 私のawaitに対する理解が足りていないようなので、もう一度基本に立ち返り試してみようと思います。
H40831

2020/08/26 05:58

とんでもないです! 自分も、非同期処理についてはまだまだ勉強中で、 メンターと契約してわからないことはいちいち質問をぶつけてます。 むずかしいですよね。お互いがんばりましょう〜
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問