LoginSignup
74
42

More than 3 years have passed since last update.

JavaScriptはシングルスレッドで実行される

Last updated at Posted at 2019-05-21

自分自身が勘違いしていたので記事にします。

問題

<!DOCTYPE html>
<html>

<head>
    <title>Document</title>
</head>

<body>
    <script>
        console.log(`Start ${new Date()}`)

        // 3秒後にCallbackと表示
        setTimeout(() => {
            console.log(`Callback ${new Date()}`)
        }, 3000)

        // 10秒間かかる処理を実行する
        const now = new Date()
        let dummy = 0
        while (new Date() - now < 10000) {
            dummy++ // 適当な計算処理
        }

        console.log(`End ${new Date()}`)
    </script>
</body>

</html>

このHTMLをブラウザで表示させると、コンソールにはStart, Callback, Endがどの順番で表示されるでしょうか?

  1. Startが表示される
  2. 3秒後にCallbackと表示されることが予約される
  3. 10秒間かかる処理を実行する
    この間に少なくとも3秒間経過するのでCallbackと表示される
  4. Endと表示される

よってStartCallbackEnd

だと思っていませんか?

残念!不正解です。

スクリーンショット 2019-05-21 11.14.17.png

実行結果

Start Tue May 21 2019 10:39:40 GMT+0900 (日本標準時)
End Tue May 21 2019 10:39:50 GMT+0900 (日本標準時)
Callback Tue May 21 2019 10:39:50 GMT+0900 (日本標準時)

実際にはStartEndCallbackの順番で実行されます。

ポイント

ここら辺がポイントです。

  • setTimeoutは規定時間後に関数の実行を予約する
  • しかし、JavaScriptはシングルスレッドで実行される
    • つまり、2つ以上の処理を並行して実行できない
    • 2つ以上の関数を同時実行できない

解説

つまり、正しくは以下のような順序になります。

  1. Startが表示される
  2. 3秒後にCallbackと表示されることが予約される
  3. 10秒間かかる処理を実行する
    この間に少なくとも3秒間経過するが、まだメインの処理が実行されているので2.の関数を実行開始できない
  4. Endと表示される
  5. メインの処理が完了して次の処理を実行可能になったので、2.の関数が実行される
    Callbackと表示される

よってStartEndCallbackの順番で実行されます。

スクリーンショット 2019-05-21 11.14.22.png

ちなみに、setTimeoutを使う場合以外でも、

  • Ajaxでの非同期処理
  • Node.jsでのファイル読み込みなどの非同期処理

などの場合もシングルスレッドなので同様の処理順になります。

74
42
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
74
42