🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
JavaScript

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

非同期処理

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

Q&A

解決済

2回答

4880閲覧

javascriptのPromiseの実行順序が分からない

ganariya

総合スコア50

JavaScript

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

非同期処理

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

1グッド

4クリップ

投稿2019/09/11 07:30

前提・実現したいこと

現在、JavaScriptの非同期処理を理解する必要があるため

  • コールバック
  • Promise
  • async/await

について勉強していました。

しかし、Promiseの挙動について不可解な点があります。

発生している問題

javascript

1function asyncFunc(val) { 2 console.log("first"); 3 return new Promise((resolve, reject) => { 4 console.log("second"); 5 resolve(val * 2); 6 }) 7} 8 9 10asyncFunc(50) 11 .then((val) => { 12 console.log(val); 13 }); 14 15console.log('here');

以上のコードをブラウザで実行したときに、実行順序が

first second here 100

のようになります。

個人的には、

first here second 100

の順番で出力されると考えていました。

上記のような順番であると考える理由

JavaScriptの勉強内で

ChromeのようなWebブラウザは

v8(ブラウザ内のjs実行エンジン)

  • シングルスレッド
  • スタック(関数・処理を積んでいく)

Web API

  • DOM
  • Timer
  • setTimeout

キュー

  • もしv8のスタックが空なら、非同期処理が終わった部分をスタックに戻す

という3構成であると考えていました。

例えば、setTimeout(f)を実行すると
まずスタックに入り
その後setTimeoutなので、Web APIだ! とブラウザが代わりに実行して(タイマーを測って)
そして、タイマーの時間になったら、キューに移し、スタックが空いている瞬間があったらfをスタックに入れて実行する。
という認識です。

そのため、上記のコードを実行すると

  1. asyncFuncをスタックに積む
  2. asyncFuncを解析すると、console.log("first")があるので実行する。
  3. return new Promiseなので、WebAPIもしくはキューに中身を打ち込む。

(Promiseは、resolve, rejectがなされるまで内部状態が変わらないので、おそらくWebAPI・キューに積まれる)

  1. console.log("here")を実行する。
  2. スタックが空いたので、Promise内を実行し、まずsecondを出力する。
  3. resolveを実行し、FulFilled状態になりthenメソッドが呼ばれる。
  4. thenメソッド内のconsole.log(val)をスタックに積んで実行する。

という流れになると想定していました。

しかし、実際の実行順序は
thenメソッドだけが後回しでそれ以外が先に実行されていました。

これはどういう実行順序、またはPromiseの仕組みなのでしょうか?

よろしくお願いいたします。

退会済みユーザー👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

これはどういう実行順序、またはPromiseの仕組みなのでしょうか?

よくある勘違いですが、new Promiseの引数に渡した関数は同期的に実行されます。

executor 関数(引用者注:new Promiseの引数となる関数)は resolve 関数と reject 関数が渡されて Promise が実装されるとすぐに実行されます (Promise コンストラクターがオブジェクトを返すよりも前に executor は実行されます)。 ―MDNより

投稿2019/09/11 07:35

maisumakun

総合スコア145975

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

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

ganariya

2019/09/11 07:57

まだ飲み込めていないのですが、new Promiseのexecuter関数が同期的に実行されるということは 上記のコードでは console.log("second")はすぐに実行されて **resolve(val*2)**のみが、キューに積まれるのでしょうか? また、同期的に実行するということは、Promiseは正確には非同期処理ではないのでしょうか?
maisumakun

2019/09/11 08:06 編集

> console.log("second")はすぐに実行されてresolve(val*2)のみが、キューに積まれるのでしょうか? いえ、このコードの場合、resolveも同期的に実行されます。.thenに与えた関数は(同期的にresolveされようが)常に非同期実行となるようになっています。 > また、同期的に実行するということは、Promiseは正確には非同期処理ではないのでしょうか? new Promise()に与える関数は、Promiseの初期化用です。非同期実行が始まる前の段階です。
ganariya

2019/09/11 08:35

ご回答ありがとうございます! Promise内はすべて基本的には同期処理で、 thenやcatchのみが非同期に実行される。 よって、then()内のconsole.log(val)のみが最後に実行されて その前にconsole.log(here)が実行されている というのであっていますでしょうか?
guest

0

asyncFuncがasyncになっていなからでは?

javascript

1async function asyncFunc(val) { 2 await console.log("first"); 3 return new Promise((resolve, reject) => { 4 console.log("second"); 5 resolve(val * 2); 6 }); 7}

全体をちゃんと書くと

javascript

1const asyncFunc=async val=>{ 2 await console.log("first"); 3 return new Promise(resolve=>{ 4 console.log("second"); 5 resolve(val * 2); 6 }); 7}; 8asyncFunc(50).then(console.log); 9console.log('here');

投稿2019/09/11 08:15

yambejp

総合スコア116690

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

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

ganariya

2019/09/11 08:40

asyncをつけると必ずPromiseが帰る、というものですね! このコードだと まずasyncFunc(50)を呼び、console.log("first")を呼ぶまで待つ。 その後に、'here'が何故か出力される(ここが違和感がして、先にProimise内は実行されないのでしょうか?) そして、Promise内のsecond, resolveを実行し、 最後にthen(val => console.log(val))を実行する流れでしょうか? (先にhereが実行されるのが違和感がします・・・ return new Promiseは、Web APIまたはキューに積まれているのでしょうか?)
yambejp

2019/09/11 09:01 編集

考え方的にはasync設定したasyncFuncのawaitが入った時点で 並行処理のhereが走るという認識でよいのでは? async設定していないasyncFuncのconsoleは resolveされるまでは同期処理で動く
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問