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

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

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

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

非同期処理

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

Q&A

解決済

2回答

2987閲覧

[Javascript] async関数内のawaitは、結果が返るまで待っていると認識していますが。

getHappiness

総合スコア11

JavaScript

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

非同期処理

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

0グッド

3クリップ

投稿2022/06/03 15:27

async / await について、質問させて頂きます。

以下の場合、コンソールログには"Leanne Graham"が表示されます。【期待通り】

Javascript

1async function access(url) { 2 const res = await fetch(url); 3 const json = await res.json(); 4 console.log(json.name); 5} 6const url = 'https://jsonplaceholder.typicode.com/users/1'; 7access(url);

以下の場合、コンソールログにはundefinedと表示されます。【期待通りでない】

Javascript

1async function access(url) { 2 const res = await fetch(url); 3 const json = res.json(); 4 console.log(json.name); 5} 6const url = 'https://jsonplaceholder.typicode.com/users/1'; 7access(url);

私の理解では、「fetch(url)」の結果(Promise.resolve)が返ってくるまで待っていて、
resに結果が入ってから次の「res.json()」が実行される認識ですので、
「res」が「undefined」とはならないのでは?という疑問です。

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

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

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

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

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

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

guest

回答2

0

ベストアンサー

2番目のコードで、res とjson と json.nameそれぞれの内容を確認するため下記のように変えてみます。

js

1async function access(url) { 2 const res = await fetch(url); 3 console.log('res: ' + res); // 追加 4 5 const json = res.json(); 6 console.log('json: ' + json); // 修正 7 console.log('json.name: ' + json.name); // 追加 8} 9const url = 'https://jsonplaceholder.typicode.com/users/1'; 10access(url);

として実行すると

> "res: [object Response]" > "json: [object Promise]" > "json.name: undefined"

と表示されます。

つまり、どうやら
・res は (undefined ではなく)Response オブジェクト
・json は Promise オブジェクト
・json.name は(当初確認できたように)undefined
らしい、ということが分かります。

まとめると、「『fetch(url)』の結果が返ってくるまで待っていて、
resに結果が入ってから次の『res.json()』が実行される」、という質問者さんの認識はほぼ合っていますが、
実行したときの結果が違います。


なぜ違いが出るのか。

① 2番目のコードの処理の流れ

const res = await fetch(url);

まずこれによりres は Responseオブジェクトに紐つけられます。

そして、次:

const json = res.json();

Responseオブジェクトのjson() メソッドは Promiseを返します
したがって、res.json() の戻り値は Promise オブジェクトとなるため、左辺の変数 json は Promise オブジェクトに紐付けられることになります。

しかし、Promise オブジェクト自体には name キーがないので
次の

console.log(json.name);

を実行すると undefined と出力されてしまいます。


② 最初のコードの処理の流れ
const res = await fetch(url);
までは①と同じです。
変数res には Response オブジェクトが紐付けられます。

次の行:

js

1const json = await res.json(); 2console.log(json.name);

async/await は Promiseのシンタックスシュガーですので、この2行は

js

1res.json().then(json => console.log(json.name));

とほぼ同じです。

これが実行されると、thenの後の引数「json」には、Promise の解決後のデータ(レスポンスの本文のテキストを JSON として解釈した結果データ)が格納されます。
具体的には、urlで指定したエンドポイントからのレスポンスJSONです。
これは name キーを持っていますので、期待する出力となります。

投稿2022/06/03 16:11

編集2022/06/04 01:02
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

getHappiness

2022/06/04 00:35

早々にご回答ご教授ありがとうございました。 処理の流れを順番に説明頂き理解できました。 「res.json()」はPromiseオブジェクトを返し、「処理待ちの状態」である為に「json.name」はname キーを持っていなかった、ですね。
退会済みユーザー

退会済みユーザー

2022/06/04 01:00 編集

コメントありがとうございます。 なお、"「処理待ちの状態」である為に「json.name」はname キーを持っていなかった"という部分が少し引っかかったので念のため。 2番目のコードで const json = res.json(); で 変数jsonに紐付けられているPromiseは、「res.json()」の処理が終わった後(解決後)もPromiseであることには変わりません。(解決前のPromiseか、解決後のPromiseであるかが異なるだけです) 仮に「res.json()」の処理が終わった後(解決後)に console.log(json.name); としても、json に紐付けられたPromiseオブジェクトは name キーをもっていないため、「undefined」 と表示されることに変わりありません。 解決後のnameキーを持っているデータを取り出すには、質問文の1番目のようにawaitを使うか、 または回答に書いたように res.json().then(json => console.log(json.name)); とする必要があります。 const json = await res.json(); とした場合は、Promiseが解決されてから、左辺の変数 json にエンドポイントから取得知ったJSONデータが紐付けられるため、期待通りの動作になります。 --- const json = res.json(); // 左辺のjson はPromiseオブジェクトに紐付けられる。 const json = await res.json(); // 左辺のjson は 最終的にエンドポイントから取得したJSON(オブジェクト)に紐付けられる。res.json() によって生成されるPromiseは内部に隠れていて見えない。 --- awaitがあるかないかだけですが、左辺 json が紐付く対象は全く異なります。 これは歴史的な経緯で言えば、 2番目については当初 res.json().then(json => console.log(json.name)); という書き方しかなかったのですが、これだと動作がわかりにくいので 文法上の技巧(シンタックスシュガー)として 1番目に近い書き方ができるようになった、という背景があります。
getHappiness

2022/06/04 13:57

追加のご教授ありがとうございました。 > 仮に「res.json()」の処理が終わった後(解決後)に console.log(json.name); としても、json に紐付けられた Promiseオブジェクトは name キーをもっていないため、「undefined」 と表示されることに変わりありません。 仰る通り、誤って理解しておりました。。解決前であろうと解決後であろうとPromiseオブジェクトに紐づいた変数にはnameキーがない、という事ですね。 今度こそ理解いたしました。本当にありがとうございました。
guest

0

fetch() と同様に、Response.json() もPromiseを返すという点に注意するとよいでしょう。

Response.json()

json() は Response インターフェイスのメソッドで、 Response のストリームを取得して完全に読み取ります。本文のテキストを JSON として解釈した結果で解決するプロミスを返します。

https://developer.mozilla.org/ja/docs/Web/API/Response/json

投稿2022/06/03 16:25

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

getHappiness

2022/06/04 00:38

早々のご回答ありがとうございました。 josn() メソッドはPromiseを返す(=非同期)のですね。リンク先も参考になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問