JS for ループで setTimeout を使用する 4 つのソリューション

JS for ループで setTimeout を使用する 4 つのソリューション

概要

まず、setTimeout 遅延の動作メカニズムを簡単に見てみましょう。 setTimeout は、まずコールバック関数を待機キューに配置し、待機領域にある他のメイン プログラムが実行された後、コールバック関数を時系列順に実行します。それは本質的には範囲の問題です。

したがって、これを実行すると、目的の出力 1.2.3.4.5 は得られず、5 つの連続した 6 が出力されます。

(var i=1; i<=5; i++) の場合 {
    setTimeout(関数タイマー() {
        コンソールにログ出力します。
     }, i*1000 );
}

これは、setTimeout が非同期で実行されるためです。for ループが実行されるたびに、setTimeout は 1 回実行されますが、内部の関数は実行されません。代わりに、タスク キューに配置され、実行を待機します。メインライン上のタスクが完了した場合にのみ、タスクキュー内のタスクが実行されます。つまり、 for ループが完全に終了するまで待機してから fun 関数を実行します。ただし、 for ループが終了すると、 i の値は 6 になっています。そのため、タイマーは 5 秒間実行されますが、コンソールの内容は 6 のままです。

(注: for ループは、開始から終了まで数マイクロ秒または数ミリ秒続く必要があります。タイマーが 1 秒経過すると、for ループはすでに完了しています。)

別のケースを見てみましょう。

(var i=1; i<=5; i++) の場合 {
    (関数() {
        setTimeout(関数タイマー() {
            コンソールにログ出力します。
        }, i*1000 );
    })();
}

setTimeout の動作メカニズムから、すべての外部メイン プログラムが最初に実行されることがわかります。for ループではクロージャが形成されますが、fun は実際のパラメーターを見つけないため、最初の例と実際の違いはなく、5 つの連続した 6 が引き続き出力されます。

解決策 1: クロージャ

クロージャを使用するのは古典的なアプローチです。

(var i=1; i<=5; i++) の場合 {
    (関数(j) {
        setTimeout(関数タイマー() {
            コンソールログ(j);
        }, j*1000 );
    })(私);
}

予想される結果は、1 から 5 までの順番の出力と一致していることがわかります。これは、実際のパラメータがタイマー内の i に強く依存しているためです。

クロージャを通して、変数 i がメモリ上に常駐します。j が出力される際、外部関数の変数値 i が参照されます。i の値はループに基づいており、setTimeout が実行されると内部の出力が決定されます。

解決策2: 構造を分割する

setTimeout の定義と呼び出しを別の部分に分けることもできます。

関数タイマー(i) {
    タイムアウトを設定します( console.log( i ), i*1000 );
}
(var i=1; i<=5; i++) の場合 {
    タイマー(i);
}

コンソールの出力は、引き続き 1 から 5 の順になっています。

解決策3:

es6 の let を使用してこの問題を解決する別の方法を次に示します。

(i=1; i<=5; i++) の場合 {
    setTimeout(関数タイマー() {
        コンソールにログ出力します。
     }, i*1000 );
}

最初の例と比較すると、この例では var が let に変更されるだけですが、コンソールには 1 から 5 が順番に出力されます。

for ループの先頭にある let は i を for ループにバインドするだけでなく、実際にループ本体の各反復に再バインドし、前の反復の終了時の値が再割り当てされるようにします。 setTimeout の function() は新しいスコープに属します。var で定義された変数は、この関数の実行スコープに渡すことはできません。let を使用してブロック変数を宣言すると、このブロックで動作できるため、function は変数 i を使用できます。この匿名関数のパラメーター スコープは for パラメーターのスコープとは異なりますが、これは this を利用して実現されています。この匿名関数のスコープはクラスの属性に多少似ており、内部メソッドで使用できます。

解決策4: setTimeoutの3番目のパラメータ

(i=1; i<=5; i++) の場合 {
    setTimeout(関数タイマー() {
        コンソールにログ出力します。
     }, i*1000, i );
}

毎回渡されるパラメータはforループから取得した値なので、1~5が順番に出力されます。

上記は、JS の for ループで setTimeout を使用するための 4 つのソリューションの詳細です。JS で setTimeout を使用する方法の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • JavaScript は setTimeout を使用してカウントダウン効果を実現します
  • JavaScript setTimeout()の基本的な使い方は何ですか?
  • JavaScript setInterval() と setTimeout() タイマー
  • settimeoutを使用するだけで、JavaScriptの動作メカニズムを確認できます。
  • setTimeout を通して JS の動作メカニズムを理解する方法
  • setTimeoutからのjs関数実行プロセスを見てみましょう
  • js setTimeout を使用してラウンドロビンアニメーションを実装する方法を学ぶ
  • JavaScript タイマーの使用状況の分析 [setTimeout と clearTimeout]
  • JS のタイマー setInterval と setTImeout の this ポイント問題の詳細な説明
  • JavaScript の setTimeout について

<<:  nginxでの共有メモリの使用に関する詳細な説明

>>:  Docker での RocketMQ の詳細なインストールと使用

推薦する

JS で if 判定をスムーズに行う方法

目次序文コードの実装アイデア 1アイデア2要約する参照ドキュメント序文プロジェクト内の小さな要件ポイ...

MySQL での order by の使用に関する詳細

目次1. はじめに2. 本文2.1 単一列のソート2.2 複数の列を並べ替える2.3 ソート方法2....

js の getBoundingClientRect() メソッドの詳細な説明

1. getBoundingClientRect() 分析getBoundingClientRect...

DOCTYPEタイプの詳細な紹介

<br />通常、HTML では次の方法で DOCTYPE を宣言します。 <!D...

Docker デプロイメント MySQL8 クラスター (マスター 1 台とスレーブ 2 台) の実装手順

目次1. CentOS 7.9 20にDockerをインストールする2. MySQL クラスターをデ...

TypeScriptにおけるunknownとanyの違いについて詳しく説明します

目次序文1. 不明 vs 任意2. 未知とあらゆるもののメンタルモデル3. まとめ要約する序文any...

Navicat がリモートで SQL Server に接続し、MySQL に変換する詳細な手順

序文最近、プロジェクトで SQL Server を使用するプログラムに遭遇しました。このデータベース...

MYSQLは継続サインイン機能を実装しており、サインイン後1日経過すると最初から開始します(SQL文)

1. テストテーブルを作成する テーブル `testsign` を作成します ( `userid`...

WindowsでMysql5.7.17のインストールと起動に失敗する問題を解決する

マシンに初めて MySQL をインストールします。オペレーティングシステムはwin7ですmysqlの...

MySQL sql_modeクエリと設定の詳細な説明

1. SQLを実行して表示する @@session.sql_mode を選択します。 グローバルレベ...

TCPパフォーマンスチューニングの実装原理とプロセス分析

3ウェイハンドシェイクフェーズクライアントSYNパケットの再試行回数sysctl -w net.ip...

ウェブサイト上のWeiboコンポーネントの再設計の詳細な紹介(写真とテキスト)

前面に書かれたWeibo コンポーネントは、サードパーティのアクセス ユーザーが開発を必要とせずに ...

MySQL マスタースレーブ同期の原理と応用

目次1. マスタースレーブ同期原理マスタースレーブ同期アーキテクチャ図(非同期同期)マスタースレーブ...

MySQL ジョイントテーブル更新デー​​タの詳細な例

1.MySQL UPDATE JOIN構文MySQL では、UPDATE ステートメントでJOIN句...

Windows 10 に付属する仮想マシンのネットワークを設定するための詳細な手順 (グラフィック チュートリアル)

1. サーバー ホストをクリックし、右側の操作リストで [仮想スイッチ管理] をクリックして、仮想...