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

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

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

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

JavaScript

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

Q&A

解決済

1回答

1609閲覧

awaitをPromise変数に使うかPromiseを返却する関数の実行結果に使うかで結果が変わる

yuzunoha123

総合スコア28

ECMAScript

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

JavaScript

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

1グッド

2クリップ

投稿2020/02/24 13:21

質問

下記のコードの関数asyncAwaitVariablesasyncAwaitDirectの違いが謎過ぎます。
awaitをPromise変数に使うかPromiseを返却する関数の実行結果に使うかで結果が変わるのはなぜなのでしょうか。

コード

JavaScript

1'use strict'; 2 3const start = new Date(); 4const callback = () => { 5 const end = new Date(); 6 const lapseMs = end.getTime() - start.getTime(); 7 return `${lapseMs}ミリ秒後`; 8}; 9const createTimeoutPromise = (ms, callback) => { 10 return new Promise(resolve => { 11 setTimeout(() => { 12 resolve(callback()); 13 }, ms); 14 }); 15}; 16const asyncAwaitVariables = async (ms, callback) => { 17 const results = []; 18 const promise0 = createTimeoutPromise(ms, callback); 19 const promise1 = createTimeoutPromise(ms, callback); 20 const promise2 = createTimeoutPromise(ms, callback); 21 results.push(await promise0); 22 results.push(await promise1); 23 results.push(await promise2); 24 console.log('asyncAwaitVariables', results); 25}; 26const asyncAwaitDirect = async (ms, callback) => { 27 const results = []; 28 results.push(await createTimeoutPromise(ms, callback)); 29 results.push(await createTimeoutPromise(ms, callback)); 30 results.push(await createTimeoutPromise(ms, callback)); 31 console.log('asyncAwaitDirect...', results); 32}; 33const main = () => { 34 const ms = 100; 35 asyncAwaitVariables(ms, callback); 36 asyncAwaitDirect(ms, callback); 37}; 38main();

出力結果

JavaScript

1asyncAwaitVariables [ '102ミリ秒後', '104ミリ秒後', '104ミリ秒後' ] 2asyncAwaitDirect... [ '104ミリ秒後', '206ミリ秒後', '306ミリ秒後' ]
shinji709👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

asyncAwaitVariables は、最初の await の時点で 3つの処理が非同期並行動作しています。1番目の処理が終われば最初のawaitから復帰し、ほぼ同時に2番目も3番目も終わっていて、その後のawaitはすぐに復帰してきます。
asyncAwaitDirect は、ひとつ処理を呼び出して処理が終わるのを await で待って、2番目を実行してawaitで終わるのを待って、3番目を実行するので、順次実行です。

asyncAwaitDirect の方も、一度変数に代入してみると違いが分かると思います。

js

1'use strict'; 2 3const start = new Date(); 4const callback = () => { 5 const end = new Date(); 6 const lapseMs = end.getTime() - start.getTime(); 7 return `${lapseMs}ミリ秒後`; 8}; 9const createTimeoutPromise = (ms, callback) => { 10 return new Promise(resolve => { 11 setTimeout(() => { 12 resolve(callback()); 13 }, ms); 14 }); 15}; 16const asyncAwaitVariables = async (ms, callback) => { 17 const results = []; 18 const promise0 = createTimeoutPromise(ms, callback); 19 const promise1 = createTimeoutPromise(ms, callback); 20 const promise2 = createTimeoutPromise(ms, callback); 21 results.push(await promise0); 22 results.push(await promise1); 23 results.push(await promise2); 24 console.log('asyncAwaitVariables', results); 25}; 26const asyncAwaitDirect = async (ms, callback) => { 27 const results = []; 28 const promise0 = createTimeoutPromise(ms, callback); 29 results.push(await promise0); 30 const promise1 = createTimeoutPromise(ms, callback); 31 results.push(await promise1); 32 const promise2 = createTimeoutPromise(ms, callback); 33 results.push(await promise2); 34 console.log('asyncAwaitDirect...', results); 35}; 36const main = () => { 37 const ms = 100; 38 asyncAwaitVariables(ms, callback); 39 asyncAwaitDirect(ms, callback); 40}; 41main();

asyncAwaitVariableの処理シーケンスを書いてみました。

asyncAwaitVariables処理フロー

asyncAwaitDirect の処理シーケンスを書いてみました。

asyncAwaitDirect処理フロー

実際の正確な処理の流れとは違う部分があるとは思いますが、だいたいの流れは理解できると思います。
Promiseキューの「終了」は該当Promseのresolveメソッド呼び出しのことです。

投稿2020/02/24 13:45

編集2020/02/26 15:26
shiracamus

総合スコア5406

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

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

yuzunoha123

2020/02/25 11:05

回答ありがとうございます!おかげで"何が起こっているのか"は分かりましたが"なぜそれが起こるのか"がわかりません>< asyncAwaitVariablesとasyncAwaitDirectの記述は等価に見えるのですが違うのでしょうか。
shiracamus

2020/02/25 11:39 編集

全然違いますよ。 const promise0 = createTimeoutPromise(ms, callback); const promise1 = createTimeoutPromise(ms, callback); const promise2 = createTimeoutPromise(ms, callback); ここまでawaitしていないので、3つの処理が同時に動けます。3つのタイマーがほぼ同時にスタートします。 一方、 results.push(await createTimeoutPromise(ms, callback)); は、この処理が終わるまでawaitで待ち合わせます。 results.pushまで終わったら、次の results.push(await createTimeoutPromise(ms, callback)); を実行します。 ひとつのタイマー処理が完全に終わってから、次のタイマーをスタートします。
shiracamus

2020/02/25 11:41

処理のタイムチャートを書けばすぐ理解できると思いますが、いま移動中なので後程書いてみます。
yuzunoha123

2020/02/25 13:13

ありがとうございます!!
yuzunoha123

2020/02/26 15:26

ありがとうございました!図まで用意してくださったおかげでスッと理解できました。いくら自分で調べてもわからず、熟練の方からご教授いただけて幸いでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問