JavaScript マクロタスクとマイクロタスクの実行順序についての簡単な説明

JavaScript マクロタスクとマイクロタスクの実行順序についての簡単な説明

1. JavaScriptはシングルスレッドです

JavaScript はシングルスレッドです。つまり、一度に実行できるのは 1 つの処理のみであり、次の処理は前の処理が完了した後にのみ実行できます。その結果、時間のかかるタスクが発生した場合、後続のコードが実行できなくなります。

その前に、同期と非同期を理解する必要があります

1. 同期タスク

    コンソールログ(123);
    コンソールログ(456);
    (i = 1; i <= 5; i++ とします) {
      コンソールにログ出力します。
    } 

名前が示すように、順番に実行する必要がある

2. 非同期タスク

    タイムアウトを設定する(() => {
      console.log('タイマー');
    }, 0)
    console.log('ウルトラマン');

通常の実行順序では、タイマーが一番上なので、最初にタイマーを出力し、次に Ultraman を出力します。

最終結果は、最初に Ultraman が出力され、次にタイマーが出力されます。これは、setTimeout が非同期タスクであるためです。

もう 1 つ知識があります。setTimeout のタイマーは、何ミリ秒遅れても非同期です。ブラウザごとに時間も異なります。ブラウザごとに違いはありますが、最小値は 0 ミリ秒と 4 ミリ秒と定義されています。

2. タスクキュー

上記のコードから、setTimeout は非同期であることがわかります。実行順序の優先順位は、同期コード > 非同期コードです。したがって、タスクキューは 2 つのカテゴリに分かれています。1. 同期タスク 2. 非同期タスク

1. 実行スタック

(1)すべての同期タスクはメインスレッド上で実行され、実行コンテキストスタックを形成します。

(2)メインスレッドの他に「タスクキュー」も存在します。非同期タスクに実行結果がある限り、イベントは「タスク キュー」に配置されます。

(3)「実行スタック」内のすべての同期タスクが実行されると、システムは「タスクキュー」を読み取り、そこにどのようなイベントが含まれているかを確認します。対応する非同期タスクは待機状態を終了し、実行スタックに入り、実行を開始します。

(4)メインスレッドは上記の3番目のステップを継続的に繰り返します。これをイベントループと呼びます。

梨をあげるだけ

二人とも外食に出かけますが、P2は外食する時間を節約します。

簡単に理解した後、非同期タスクにおけるマクロタスクとマイクロタスクについて詳しく見ていきましょう。

個人的な理解: マクロタスクとマイクロタスクは、非同期の 2 つの形式として理解できます。非同期には、マクロタスクとマイクロタスクという 2 つの子があります。

マクロタスク内のメソッド: 1. スクリプト (エントリポイントとして外部同期コードとして理解できます) 2. setTimeout/setInterval

マイクロタスクのメソッド: 1. Promise 2. nextTick

実行順序は、マイクロタスクが最初に出力され、次にマクロタスクが出力される。

証拠なしにコードを言う

    タイムアウトを設定する(() => {
      console.log('タイマー');
    }, 0)
    新しいPromise((resolve) => {
      console.log('同期コード')  
      解決('非同期コード')
    }).then((res) => {
      コンソールログ(res);   
    })
    console.log('ウルトラマン'); 

new Promise はコンストラクタを作成しますが、これは同期プロセスです。一方、.then メソッドは非同期であるため、コードは最初に同期的に実行されます > microtask > macrotask

実行プロセスをより詳しく説明するため、次の図は少し複雑になっています。

これらの写真は組み合わせて

setTimeoutの理解を深める

質問 1: 同期コードが実行された後、setTimeout は 0 からカウントを開始しますか?

    タイムアウトを設定する(() => {
      コンソールログに'setTimeout'と入力します。
    }, 1000);
    console.log('ウルトラマン');
    (i = 0; i < 1000; i++ とします) {
      コンソールログ('');
    } 

ここで、for ループ内では、setTimeout によってタイマー モジュールも開始されることを指摘しておきます。したがって、メイン スレッドが実行されると、タイマー モジュールはすでに実行を開始しているため、実行に 1 秒待つ必要はありません。

(同期が完了したと想定して計測を開始しないでください。)

質問 2: 2 つのタイマーのうち、上のタイマーを最初に実行し、次に下のタイマーを実行する必要がありますか?

テストでは、誰が最初に実行するかを確認するためのタイマーを追加するだけです。

    タイムアウトを設定する(() => {
      コンソールログ('setTimeout1');
    }, 2000);
    タイムアウトを設定する(() => {
      コンソールログ('setTimeout2');
    }, 1000); 

タイマーが 2 つある場合、時間の短い方が最初にメイン スレッドで実行されることがわかります。

質問 3: 変数が 0 として定義され、2 つの同一のタイマー イベントが設定されている場合、出力はどうなりますか? (インタビューの質問)

    私 = 0
    タイムアウトを設定する(() => {
      コンソールログ(++i); //1
    }, 1000);
    タイムアウトを設定する(() => {
      コンソールログ(++i); //2 
    }, 1000);

これで、タイマー マクロ タスクは同時に実行されるのではなく、順番に実行されることがおわかりいただけたと思います。 !

マクロタスクとマイクロタスクの実行順序に関する面接の質問

    コンソールログ('1');
 
    setTimeout(関数() {
      コンソールログ('2');
      process.nextTick(関数() {
        コンソールログ('3');
      })
      新しいPromise(関数(resolve) {
        コンソールログ('4');
        解決する();
      }).then(関数() {
        コンソールログ('5')
      })
    })
    process.nextTick(関数() {
      コンソールログ('6');
    })
    新しいPromise(関数(resolve) {
      コンソールログ('7');
      解決する();
    }).then(関数() {
      コンソールログ('8')
    })
 
    setTimeout(関数() {
      コンソールログ('9');
      process.nextTick(関数() {
        コンソールログ('10');
      })
      新しいPromise(関数(resolve) {
        コンソールログ('11');
        解決する();
      }).then(関数() {
        コンソールログ('12')
      })
    })

答え:

外部同期コードの最初の実行ラウンド: 1 7

マイクロタスク実行の2回目のラウンド: 6 8

マクロタスクの3回目のラウンド: 最初のsetTimeout: 同期 2 4 マイクロタスク 3 5 2番目のsetTimeout: 同期 9 11 マイクロタスク 10 12

全体の答え: 1、7、6、8、2、4、3、5、9、11、10、12

これで、JavaScript マクロタスクとマイクロタスクの実行順序に関する記事は終了です。JavaScript マクロタスクとマイクロタスクの実行順序の詳細については、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • JavaScript のマクロタスクとマイクロタスクの詳細
  • js のマクロタスクとマイクロタスクについての簡単な説明
  • JavaScript マクロタスクとマイクロタスク
  • JavaScript イベント ループ マイクロタスクとマクロタスク キューの原理に関する簡単な説明
  • JavaScript イベント ループとマクロタスクおよびマイクロタスクの原則の分析
  • JS イベントループの仕組み イベントループ マクロタスク マイクロタスク 原理分析
  • JavaScript のマイクロタスクとマクロタスクの説明

<<:  Linux viコマンドの知識ポイントと使い方のまとめ

>>:  よく使用される MySQL 関数の完全なリスト (分類および要約)

推薦する

データベースSQL SELECTクエリの仕組み

私たちは Web 開発者として、プロの DBA ではありませんが、データベースなしではやっていけませ...

Vue axios インターセプターは、繰り返しリクエストのキャンセルによく使用されます。

導入前回の記事では、axios のシンプルなカプセル化と、axios インターセプターの適用シナリオ...

Linux の sudo 脆弱性により不正な特権アクセスが発生する可能性がある

Linux で新たに発見された sudo の脆弱性を悪用すると、特定のユーザーが root としてコ...

MySQL 整合性制約の例の詳細な説明

この記事では、MySQL の整合性制約について説明します。ご参考までに、詳細は以下の通りです。メイン...

HTMLは入力完了を検出する機能を実装する

入力が進行中かどうかを検出するには、「onInput(event)」を使用しますコンテンツが変更され...

jsはカスタムドロップダウンボックスを実装します

この記事の例では、カスタムドロップダウンボックスを実装するためのjsの具体的なコードを参考までに共有...

MySQLテーブルパーティショニングプログラムを変更する方法

MySQLテーブルパーティショニングプログラムを変更する方法1. サブテーブルの実装の原則は次のとお...

Pagoda Panel のインストール時にサーバーがデータベースにリモート接続できない問題の解決策

自分のウェブサイトを構築する予定なので、618 プロモーションを利用して Tencent Cloud...

HTML コードを書くための 30 のヒント

1. HTMLタグは常に閉じる前のページのソース コードでは、次のような記述がよく見られます。 &l...

Linux で特殊文字のファイル名やディレクトリを削除する方法

inode番号でファイルを削除するまずls -iを使用して、削除するファイルのinode番号を見つけ...

複数ページ通信を実現する JavaScript の sharedWorker の詳細な例

こんなことがありました。今日はGitHubで遊んでいました。最初はログインせずにいくつかのページを閲...

Nginx に lua-nginx-module モジュールをインストールする方法

ngx_lua_module は、lua パーサーを nginx に埋め込み、lua 言語で記述され...

CSS フロートプロパティ図 フロートプロパティの詳細

CSS の float プロパティを正しく使用することは、カバーすべき内容が多く、ブラウザの互換性の...

MySQL 学習のまとめ: InnoDB ストレージ エンジンのアーキテクチャ設計の予備的な理解

1. ストレージエンジン前のセクションでは、SQL 実行プランは、エグゼキュータ コンポーネントがス...

MySQL の簡単な分析 - MVCC

バージョンチェーンInnoDB エンジン テーブルでは、クラスター化インデックス レコードに 2 つ...