コンピューター ウィンドウズ インターネット

Javascriptのタイマー(setInterval、setTimeout)。 jQuery関数の例setTimeout()Javascriptは、複数のタイマーが同時にsetintervalを実行するのを防ぎます

JavaScriptタイムアウトは、指定された時間遅延(ミリ秒単位)の後にコードの一部を実行するネイティブJavaScript関数です。 これは、ユーザーがページでしばらく時間を過ごした後にポップアップを表示する必要がある場合に便利です。 または、しばらくしてから要素にカーソルを合わせると、エフェクトが開始されます。 このようにして、ユーザーが誤ってホバーした場合に、誤ってエフェクトがトリガーされるのを防ぐことができます。

簡単なsetTimeoutの例

この機能の効果を示すために、次のデモをご覧になることをお勧めします。このデモでは、ボタンがクリックされてから2秒後にポップアップウィンドウが表示されます。

デモを見る

構文

MDNドキュメントには、setTimeoutの次の構文が記載されています。

var timeoutID = window.setTimeout(func、); var timeoutID = window.setTimeout(code、);

  • timeoutIDは、タイマーを無効にするためにclearTimeout()と組み合わせて使用​​できる数値IDです。
  • funcは実行される関数です。
  • コード( 代替構文で)-実行されるコード行。
  • delay-関数が実行されるまでの遅延時間(ミリ秒単位)。 デフォルトは0です。

setTimeout vs window.setTimeout

上記の構文はwindow.setTimeoutを使用します。 どうして?

実際、setTimeoutとwindow.setTimeoutは実質的に同じ関数です。 唯一の違いは、2番目の式では、グローバルウィンドウオブジェクトのプロパティとしてsetTimeoutメソッドを使用することです。

個人的には、これはコードを非常に複雑にするだけだと思います。 優先順位に従って検索して返すことができる代替のJavaScriptタイムアウトメソッドを定義すると、さらに大きな問題が発生します。

このチュートリアルでは、ウィンドウオブジェクトをいじりたくありませんが、一般的に、どの構文を使用するかはあなた次第です。

使用例

これは関数の名前である可能性があります。

function explode()(alert( "Boom!");)setTimeout(explode、2000);

関数を参照する変数:

var explode = function()(alert( "Boom!");); setTimeout(explode、2000);

または無名関数:

setTimeout(function()(alert( "Boom!");)、2000);

  • このようなコードは認識が不十分であるため、最新化やデバッグが困難になります。
  • これには、潜在的な脆弱性となる可能性のあるeval()メソッドの使用が含まれます。
  • このメソッドは実行する必要があるため、他のメソッドよりも低速です JavaScriptインタープリター.

また、JavaScriptタイムアウトのalertメソッドを使用してコードをテストしていることにも注意してください。

setTimoutへのパラメーターの受け渡し

最初に ( その上、クロスブラウザ)バリアントでは、setTimeoutで実行されるコールバック関数にパラメーターを渡します。

次の例では、greetings配列からランダムな挨拶を抽出し、それをパラメーターとしてgreet()関数に渡します。この関数は、setTimeoutによって1秒の遅延で実行されます。

function greet(greeting)(console.log(greeting);)function getRandom(arr)(return arr;)var Greetings = ["Hello"、 "Bonjour"、 "Guten Tag"]、randomGreeting = getRandom(greetings); setTimeout(function()(greet(randomGreeting);)、1000);

デモを見る

別の方法

この記事の冒頭の構文には、JavaScriptタイムアウトによって実行されるコールバック関数にパラメーターを渡すために使用できる別のメソッドがあります。 このメソッドは、遅延後のすべてのパラメーターの出力を意味します。

前の例に基づいて、次のようになります。

setTimeout(greet、1000、randomGreeting);

このメソッドは、渡されたパラメーターが定義されていないIE9以下では機能しません。 しかし、この問題を解決するには MDNには特別なポリフィルがあります.

関連する問題と「これ」

setTimeoutによって実行されるコードは、それを呼び出した関数とは別に実行されます。 このため、特定の問題に直面しています。thisキーワードは解決策として使用できます。

var person =(firstName: "Jim"、introduce:function()(console.log( "Hi、I" m "+ this.firstName);)); person.introduce(); //出力:Hi、I" mジムsetTimeout(person.introduce、50); //出力:こんにちは、私は「未定義です

この結論の理由は、最初の例ではこれがpersonオブジェクトにつながり、2番目の例ではfirstNameプロパティを持たないグローバルウィンドウオブジェクトを指しているという事実にあります。

この不整合を取り除くには、いくつかの方法を使用できます。

これを強制的に設定します

これは、このキーの値として呼び出されたときに特定の値を使用する新しい関数を作成するメソッドであるbind()を使用して実行できます。 この場合、指定された人物オブジェクトです。 これにより、結果として次のことがわかります。

setTimeout(person.introduce.bind(person)、50);

注:bindメソッドはECMAScript 5で導入されました。つまり、最新のブラウザーでのみ機能します。 また、適用するとランタイムエラーが発生する場合もあります JavaScript「関数タイムアウトエラー」.

ライブラリを使用する

多くのライブラリには、この問題を解決するために必要な組み込み関数が含まれています。 たとえば、jQuery.proxy()メソッド。 関数を受け取り、常に特定のコンテキストを使用する新しい関数を返します。 この場合、コンテキストは次のようになります。

setTimeout($。proxy(person.introduce、person)、50);

デモを見る

タイマーを無効にする

setTimeoutの戻り値は、clearTimeout()関数を使用してタイマーを無効にするために使用できる数値IDです。

var timer = setTimeout(myFunction、3000); clearTimeout(タイマー);

実際の動作を見てみましょう。 次の例では、ボタンをクリックすると「 カウントダウンを開始」、カウントダウンが始まります。 それが終わった後、子猫は彼らのものを手に入れます。 しかし、ボタンを押すと「 カウントダウンを停止します"、JavaScriptのタイムアウトが停止してリセットされます。

例を見る

まとめましょう

setTimeoutは非同期関数です。つまり、この関数への受信した呼び出しはキューに入れられ、スタック上の他のすべてのアクションが完了した後にのみ実行されます。 他の関数や別のスレッドと同時に実行することはできません。

JavaScriptタイマーがどのように機能するかを理解することは非常に重要です。 多くの場合、それらの動作はマルチスレッドの直感的な認識と一致しません。これは、実際には同じスレッドで実行されているためです。 タイマーを制御できる4つの関数を見てみましょう。

  • var id = setTimeout(fn、delay); -指定された遅延後に指定された関数を呼び出す単純なタイマーを作成します。 この関数は、タイマーを一時停止できる一意のIDを返します。
  • var id = setInterval(fn、delay); -setTimeoutに似ていますが、指定された間隔で(停止するまで)関数を継続的に呼び出します。
  • clearInterval(id);、 clearTimeout(id); -タイマーID(上記の関数の1つによって返される)を受け入れ、コールバック「a」の実行を停止します。
考慮すべき主なアイデアは、タイマーの遅延期間の精度は保証されないということです。 まず、ブラウザーは、同じスレッドですべての非同期JavaScriptイベント(マウスクリックやタイマーなど)を、イベントが順番に実行されたときにのみ実行します。 これは、次の図で最もよく示されています。

この図には把握すべき情報がたくさんありますが、これを理解することで、JavaScriptの非同期実行がどのように機能するかをより深く理解できます。 この図は、時間をミリ秒単位で垂直に表しており、青いブロックは、実行されたJavaScriptコードのブロックを表しています。 たとえば、最初のブロックは平均18ミリ秒で実行され、マウスクリックは約11ミリ秒で実行をブロックします。

JavaScriptは(実行のシングルスレッドの性質のために)コードの1つのチャンクのみを実行でき、各チャンクは他の非同期イベントの実行をブロックします。 つまり、非同期イベント(マウスクリック、タイマー呼び出し、XMLHttpリクエストの完了など)が発生すると、キューに追加されて後で実行されます(もちろん、実装はブラウザーによって異なりますが、これを「キュー」と呼ぶことに同意しましょう)..。

まず、JavaScriptブロック内で2つのタイマーが開始するとします。10msの遅延のあるsetTimeoutと同じ遅延のあるsetIntervalです。 タイマーの開始時期によっては、コードの最初のブロックがまだ完了していないときにタイマーが起動します。 ただし、すぐには起動しないことに注意してください(シングルスレッドのため不可能です)。 代わりに、据え置き関数はキューに入れられ、次に利用可能な時間に実行されます。

また、最初のJavaScriptブロックの実行中に、マウスクリックが発生します。 この非同期イベントのハンドラー(および予測できないため非同期)は、現時点では直接実行できないため、タイマーのようにキューにも入ります。

JavaScriptコードの最初のブロックが実行された後、ブラウザは「実行を待っているものは何ですか?」という質問をします。 この場合、マウスクリックハンドラーとタイマーは保留状態です。 ブラウザはそのうちの1つ(クリックハンドラ)を選択して実行します。 タイマーは、実行キューで次に利用可能な時間のチャンクを待ちます。

マウスクリックハンドラーの実行中に、最初の間隔コールバックが発生することに注意してください。 タイマーコールバックと同様に、キューに入れられます。 ただし、intervalが再び発生すると(timer-callbackの実行中に)、キューから削除されることに注意してください。 大量のコードの実行中にすべてのinterval-callbackがキューに入れられた場合、完了までの遅延なしに一連の関数が呼び出されるのを待機することになります。代わりに、ブラウザーは関数がなくなるまで待機する傾向があります。キューに別の1つを追加する前にキューに入れます。

したがって、インターバルコールバックの3回目のアクティブ化が、すでに実行されている瞬間と一致する場合を観察できます。 これは重要なポイントを示しています。間隔は現在実行されているものを気にせず、実行間の遅延期間を考慮せずにキューに追加されます。

最後に、2番目のインターバルコールバックが完了した後、JavaScriptエンジンが実行するものが何も残っていないことがわかります。 これは、ブラウザが新しい非同期イベントを再び待機していることを意味します。 これは50msマークで発生し、interval-callbackが再び発生します。 この時点では、それをブロックするものは何もないので、すぐに機能します。

setTimeoutとsetIntervalの違いをよく説明する例を見てみましょう。
setTimeout(function()(/ *コードの長いブロック... * / setTimeout(arguments.callee、10);)、10); setInterval(function()(/ *コードの長いブロック... * /)、10);
これらの2つのオプションは一見同等ですが、実際にはそうではありません。 setTimeoutを使用するコードは、前の呼び出しから常に少なくとも10ミリ秒の遅延があります(それより長くなることもありますが、少なくなることはありません)。一方、setIntervalを使用するコードは、前の呼び出しがいつ実行されたかに関係なく、10ミリ秒ごとに呼び出される傾向があります。

上記を要約しましょう:
-JavaScriptエンジンはシングルスレッド環境を使用し、非同期イベントを実行を待機するキューに変換します。
-setTimeout関数とsetInterval関数は、非同期コードでは根本的に異なる方法で実行されます。
-現時点でタイマーを実行できない場合は、次の実行ポイントまで遅延します(希望の遅延より長くなります)。
-間隔(setInterval)は、実行に指定された遅延よりも時間がかかる場合、遅延なしで次々に実行できます。

これらはすべて、開発にとって非常に重要な情報です。 JavaScriptエンジンがどのように機能するかを知ることは、特に多くの非同期イベント(頻繁に発生する)で、高度なアプリケーションを構築するための優れた基盤となります。

  • から:
  • 登録済み: 2014.07.08
  • 投稿: 3,896
  • 好きなもの: 497

トピック:SetTimeOutとSetInterval、どちらをJavaScriptで使用するのが良いですか?

一定の間隔でコードを複数回実行するには、関数を使用します setInterval..。 ただし、主にブラウザごとに動作が異なるなど、いくつかの欠点があります。

最初の違いは、タイマーが次の開始に設定されたときの違いです。 小さなテストを作成しましょう。前回の実行の開始から終了までの経過時間を測定します。

var d1 =新しい日付()、d2 =新しい日付(); setInterval(function()(var d = new Date(); document.body.innerHTML + =(d --d1)+ "" +(d --d2)+ "
"; //関数の先頭にラベルを付けるd1 = new Date(); while(new Date()-d1< 200); // ничего не делаем 200 миллисекунд // И в конце функции d2 = new Date(); }, 1000);

出力は、2行目から情報を提供します。

Firefox、Opera、Safari、Chromeでは、状況は似ています。最初の数値はほぼ1000に等しく、2番目の数値は200未満になります。 違いは値の範囲のみになります。 ChromeとOperaの最小のバリエーション。

2 返信 PunBB (PunBB 2017.06.08 16:45編集)

  • から: モスクワ、Sovkhoznay 3、apt。 98
  • 登録済み: 2014.07.08
  • 投稿: 3,896
  • 好きなもの: 497

目立たず、再現が難しいもう1つの違いは、多くの問題を引き起こす可能性があることですが、システム時間の変化に対する抵抗力です。 次のテストを実行する場合

setInterval(function()(document.body.innerHTML = Math.random();)、500);

起動後、システム時刻を1分戻します。その後、FirefoxおよびSafariブラウザーでは、数値の変更が一時停止し、1分後に再び起動します。 もちろん、システム時刻の手動変換は非常にまれな状況ですが、多くのシステムはインターネット上のサーバーと時刻を自動的に同期するように構成されているため、状況によってはこの要素を無視できない場合があります。

setInterval関数のもう1つの小さな欠点は、そのアクションを停止できるようにするために、その識別子をどこかに覚えておく必要があることです。これは必ずしも便利ではありません。

3 返信 PunBB

  • から: モスクワ、Sovkhoznay 3、apt。 98
  • 登録済み: 2014.07.08
  • 投稿: 3,896
  • 好きなもの: 497

Re:SetTimeOutとSetInterval、JavaScriptで使用する方が良いですか?

リストされているsetIntervalの欠点を取り除くために、複数のsetTimeoutを使用できます。

setIntervalの重要な代替手段は、再帰的なsetTimeoutです。

/ **代わりに:var timerId = setInterval(function()(alert( "tick");)、2000); * / var timerId = setTimeout(function tick()(alert( "tick"); timerId = setTimeout(tick、2000);)、2000);

上記のコードでは、次の実行は前の実行の直後にスケジュールされています。

再帰的なsetTimeoutは、setIntervalよりも柔軟なタイミング方法です。これは、現在の実行の結果に応じて、次の実行までの時間を異なる方法でスケジュールできるためです。

たとえば、5秒ごとにサーバーをポーリングして新しいデータを取得するサービスがあります。 サーバーが過負荷の場合は、ポーリング間隔を10、20、60秒に増やすことができます...そして、すべてが正常化されたら、それを元に戻します。

プロセッサをロードするタスクが定期的にある場合は、それらの実行に費やされた時間を見積もり、遅かれ早かれ次の起動をスケジュールできます。

4 返信 PunBB

  • から: モスクワ、Sovkhoznay 3、apt。 98
  • 登録済み: 2014.07.08
  • 投稿: 3,896
  • 好きなもの: 497

Re:SetTimeOutとSetInterval、JavaScriptで使用する方が良いですか?

再帰的なsetTimeoutは、呼び出し間の一時停止を保証しますが、setIntervalは保証しません。

2つのコードを比較してみましょう。 最初のものはsetIntervalを使用します:

var i = 1; setInterval(function()(func(i);)、100);

2番目は再帰的なsetTimeoutを使用します:

var i = 1; setTimeout(function run()(func(i); setTimeout(run、100);)、100);

setIntervalを使用すると、内部タイマーは100ミリ秒ごとに正確に起動し、func(i)を呼び出します。

setIntervalを使用したfunc呼び出し間の実際の一時停止は、コードで指定されているよりも短くなっています。

これは当然のことです。関数の動作時間はまったく考慮されていないため、間隔の一部を「食い尽くす」からです。

また、funcが予想よりも複雑で、実行に100ミリ秒以上かかった可能性もあります。

この場合、インタープリターは関数が完了するのを待ってからタイマーをチェックし、setIntervalを呼び出す時間がすでに来ている(または過ぎている)場合は、次の呼び出しがすぐに発生します。

関数がsetIntervalpauseより長くかかる場合、呼び出しはまったく中断することなく発生します。

5 返信 先輩

  • から: エルサレム
  • 登録済み: 2015.06.02
  • 投稿: 958
  • 好きなもの: 274

Re:SetTimeOutとSetInterval、JavaScriptで使用する方が良いですか?

それはすべて、目前のタスクに依存します。 最初に、SetTimeOutを使用してタイマーを1回開始し、SetIntervalを使用してループを開始します。 ただし、両方の関数を使用してスクリプトをループすることができます。たとえば、SetTimeOut関数で再帰的に実行すると、SetIntervalと同様の実用的な方法で動作します。

現時点でのSetIntervalの欠点は、スクリプト(関数)自体の実行時間が考慮されていないことです。たとえば、大量のリクエストに使用すると、間隔時間が大幅に短縮され、ブラウザによって異なる場合があります。

しかし、繰り返しますが、関数または要求が最小化されている場合、エンドユーザーは違いを感じる可能性が低くなります。
したがって、何を使用するかは、誰もが自分で決めます。

ソース:http://learn.javascript.ru/settimeout-setinterval

ほとんどすべてのJavaScript実装には、指定された期間の後に関数呼び出しをスケジュールできる内部スケジューリングタイマーがあります。

特に、この機能はブラウザーとNode.JSサーバーでサポートされています。

setTimeout

構文:

var timerId = setTimeout(func / code、delay [、arg1、arg2 ...])

オプション:

  • func / code
    • 実行する関数またはコード行。
    • この文字列は互換性のためにサポートされているため、お勧めしません。
  • 遅れ
    • ミリ秒単位の遅延、1000ミリ秒は1秒に相当します。
  • arg1、arg2..。
    • 関数に渡す引数。 IE9ではサポートされていません-。
    • 関数は、delayパラメーターで指定された時間の後に実行されます。

たとえば、次のコードは1秒後にアラート(「Hello」)を呼び出します。

関数func()(アラート( "こんにちは");)setTimeout(func、1000);

最初の引数が文字列の場合、インタプリタはその文字列から無名関数を作成します。

つまり、このようなレコードはまったく同じように機能します。

SetTimeout( "alert(" Hello ")"、1000);

代わりに無名関数を使用してください:

SetTimeout( 関数 ()(アラート( "こんにちは"))、1000);

関数パラメーターとコンテキスト

最新のすべてのブラウザーでは、IE10を念頭に置いて、setTimeoutを使用して関数パラメーターを指定できます。

以下の例では、IE9-を除くすべての場所に「こんにちは、私はVasyaです」と表示されます。

関数sayHi(誰)(アラート( "こんにちは、私は" + who);)setTimeout(sayHi、1000、 "Vasya");

...ただし、ほとんどの場合、古いIEのサポートが必要であり、引数を指定することはできません。 したがって、それらを渡すために、呼び出しは無名関数でラップされます。

関数sayHi(誰)(アラート( "こんにちは、私だよ" + who);)setTimeout( 関数 ()(sayHi( "Vasya"))、1000);

setTimeoutを介して呼び出すと、このコンテキストは渡されません。

特に、setTimeoutを介してオブジェクトのメソッドを呼び出すことは、グローバルコンテキストで機能します。 これにより、誤った結果が生じる可能性があります。

たとえば、1秒後にuser.sayHi()を呼び出しましょう。

関数ユーザー(id) 関数 ()(アラート(this .id);); )var user = new User(12345); setTimeout(user.sayHi、1000); // 12345が必要ですが、「undefined」と出力されます

setTimeoutはグローバルコンテキストでuser.sayHi関数を実行するため、これを介してオブジェクトにアクセスすることはできません。

つまり、これら2つのsetTimeoutの呼び出しは同じことを行います。

//(1)1行のsetTimeout(user.sayHi、1000); //(2)2行で同じこと var func = user.sayHi; setTimeout(func、1000);

幸い、この問題は中間関数を作成することでも簡単に解決できます。

関数ユーザー(id)(this .id = id; this .sayHi = 関数 ()(アラート(this .id);); )var user = new User(12345); setTimeout( 関数 ()(user.sayHi();)、1000);

ラッパー関数は、ブラウザー間で引数を渡し、実行コンテキストを格納するために使用されます。

実行をキャンセルする

setTimeout関数は、アクションをキャンセルするために使用できるtimerIdを返します。

構文:

ClearTimeout(timerId)

次の例では、タイムアウトを設定してから削除します(考えを変えます)。 その結果、何も起こりません。

var timerId = setTimeout( 関数 ()(アラート(1))、1000); clearTimeout(timerId);

setInterval

setIntervalメソッドの構文はsetTimeoutに似ています。

var timerId = setInterval(func / code、delay [、arg1、arg2 ...])

引数の意味は同じです。 ただし、setTimeoutとは異なり、関数の実行は1回ではなく、指定された時間間隔で定期的に繰り返されます。 次のコマンドを呼び出すことで実行を停止できます。

ClearInterval(timerId)

次の例では、起動時に、[停止]ボタンをクリックするまで2秒ごとにメッセージが表示されます。

<input type = "button" onclick = "clearInterval(timer)" value = "(!LANG:Stop" > !} <スクリプト> var i = 1; var timer = setInterval( 関数 ()(アラート(i ++))、2000);スクリプト>

setIntervalでのコールのキューイングとオーバーレイ

setInterval(function、delay)を呼び出すと、指定された時間間隔の後に関数が実行されます。 しかし、ここには微妙な点があります。

実際、呼び出し間の一時停止は指定された間隔よりも短くなっています。

たとえば、setInterval(function()(func(i ++))、100)を取ります。 100msごとにfuncを実行し、毎回カウンターをインクリメントします。

下の図で、赤いブロックはfuncの実行時間です。 ブロック間の時間は機能の開始間の時間であり、設定された遅延よりも短いです!

つまり、ブラウザは、関数自体の実行時間を考慮せずに、100ミリ秒ごとに関数の起動をきちんと開始します。

関数の実行に遅延よりも時間がかかる場合があります。 たとえば、関数は複雑で、レイテンシーは小さいです。 または、関数には、実行スレッドをブロックするアラート/確認/プロンプトステートメントが含まれています。 この場合、興味深いことが始まります。

ブラウザがビジーであるために機能を開始できない場合は、ブラウザが解放されるとすぐにキューに入れられて実行されます。

次の画像は、実行に時間がかかる関数で何が起こっているかを示しています。

setIntervalによって開始された関数呼び出しがキューに追加され、可能になるとすぐに発生します。

関数の2回目の実行は、最初の実行の終了直後に発生します。

実行は複数回キューに入れられません。

関数の実行に複数のスケジュールされた実行よりも時間がかかる場合でも、関数は1回キューに残ります。 したがって、ローンチの「蓄積」はありません。

次の画像では、setIntervalは200ミリ秒で関数を実行しようとし、呼び出しをキューに入れます。 300msと400msで、タイマーは再びウェイクアップしますが、何も通過しません。

setInterval(function、delay)を呼び出しても、実行間の実際の遅延は保証されません。

実際の遅延が指定された遅延よりも大きい場合と小さい場合があります。 一般に、少なくとも何らかの遅延が発生することは事実ではありません。

ネストされたsetTimeoutの繰り返し

定期的な繰り返しだけでなく、起動間の遅延が必要な場合は、関数を実行するたびにsetTimeoutを再設定する必要があります。

以下は、2秒間隔でアラートを発行する例です。

<input type = "button" onclick = "clearTimeout(timer)" value = "(!LANG:Stop" > !} <スクリプト> var i = 1; var timer = setTimeout( 関数実行()(アラート(i ++);タイマー= setTimeout(run、2000);)、2000);スクリプト>

実行タイムラインの実行間に固定の遅延があります。 100msの遅延の図:

最小タイマー遅延

ブラウザタイマーのレイテンシは可能な限り低くなっています。 最近のブラウザでは、約0から4ミリ秒まで変化します。 古いものでは、それはより高く、15msに達する可能性があります。

標準によると、最小遅延は4msです。 したがって、setTimeout(..、1)とsetTimeout(..、4)の間に違いはありません。

待ち時間がゼロのsetTimeoutおよびsetIntervalの動作は、ブラウザー固有です。

  1. Operaでは、setTimeout(..、0)はsetTimeout(..、4)と同じです。 setTimeout(..、2)よりも実行頻度が低くなります。 これはこのブラウザの機能です。
  2. Internet Explorerでは、ゼロ遅延setInterval(..、0)は失敗します。 これは特にsetIntervalに適用されます。 setTimeout(..、0)は正常に機能します。

実際の応答頻度

トリガーされる頻度ははるかに低くなります。場合によっては、遅延が4ミリ秒ではなく、30ミリ秒または1000ミリ秒になることもあります。

ほとんどのブラウザ(そもそもデスクトップ)は、タブが非アクティブであっても、setTimeout / setIntervalを実行し続けます。 同時に、それらの多く(Chrome、FF、IE10)は、最小タイマー頻度を1秒あたり1回に減らします。 タイマーは「バックグラウンド」タブで機能することがわかりましたが、めったにありません。

ラップトップでバッテリー電源で実行している場合、ブラウザーはコードの実行頻度を減らしてバッテリー電力を節約するために頻度を下げることもできます。 IEはこれで特に有名です。 設定によっては、最大数回の削減が可能です。 プロセッサの負荷が大きすぎると、JavaScriptがタイマーを時間内に処理できない場合があります。 これにより、setIntervalの実行の一部がスキップされます。

結論:4msの周波数でガイドする必要がありますが、それを当てにするべきではありません。

コンソールへの間隔の出力呼び出し間の間隔をカウントするコードは、次のようになります。

var timeMark =新しい日付; setTimeout( 関数go()(var diff = new Date-timeMark; //ページの代わりにコンソールに別の遅延を出力します console .log(diff); //最後の時間を覚えておいてください //呼び出し間の遅延を正確に測定する timeMark =新しい日付; setTimeout(go、100); )、100);

setTimeout(func、0)トリック

このトリックは、JavaScriptハックの年代記を入力する価値があります。

現在のスクリプトの終了後に関数を実行する場合、関数はsetTimeout(func、0)でラップされます。

重要なのは、setTimeoutが関数をすぐに実行することは決してないということです。 彼はその実装を計画しているだけです。 ただし、JavaScriptインタープリターは、現在のスクリプトの実行後にのみ、計画された関数の実行を開始します。

標準では、setTimeoutはとにかく遅延が0の関数を実行できません。前述したように、通常、遅延は4ミリ秒になります。 ただし、ここで重要なのは、どのような場合でも実行は現在のコードの実行後に行われるということです。

例えば:

var result; 関数showResult()(アラート(結果);)setTimeout(showResult、0); 結果= 2 * 2; // 4を出力します

合計

setInterval(func、delay)メソッドとsetTimeout(func、delay)メソッドを使用すると、funcを定期的に/遅延ミリ秒後に1回実行できます。

どちらのメソッドもタイマーIDを返します。 clearInterval / clearTimeoutを呼び出して実行を停止するために使用されます。

| | setInterval | setTimeout | || ----------- | ---------- | | タイミング| 厳密にタイマーで呼び出しがあります。 インタプリタがビジーの場合、1回の呼び出しがキューに入ります。 関数の実行時間は考慮されないため、ある実行の終了から別の実行の開始までの時間間隔は異なる場合があります。 | 実行間の固定休止が必要な場合、setIntervalの代わりにsetTimeoutへの再帰呼び出しが使用されます。 | | 遅延| 最小遅延:4ms。 | 最小遅延:4ms。 | | ブラウザの機能| 遅延0はIEでは機能しません| Operaでは、ゼロレイテンシーは4msに相当し、非標準の1ms、2ms、3msを含む他の遅延は正確に処理されます。 |

スクリプト言語でのプログラミングでは、定期的に一時停止を作成する必要があります。つまり、プログラムの実行をしばらく中断してから、作業を続行します。 たとえば、VBSおよびPHPスクリプトでは、次の方法が可能です。

VBS:wscript.sleep 1500(1.5秒間停止)

PHP:スリープ(10); (10秒間停止)

このような一時停止中、ランタイムシステム(PHPまたはVBS) 何もしない..。 このようなものをJavascriptで直感的に使用しようとする開発者は、不愉快に驚かれることでしょう。 Javascriptで一時停止を作成しようとしたときの一般的なエラーは、次のようになります。

関数badtest()(for(var i = 1; i< 10; i++) { window.setTimeout("document.getElementById("test1").value += " + i, 900) } }

ループを通過するときに、次の数字を描くことになると、あなたは思いますか? setTimeout正直にJavascriptの作業を停止し、0.9秒待ってから、入力フィールドの最後に必要な数を追加してから、作業を続行します。 しかし実際にはそうではありません: setIntervalsetTimeout Javascriptでは、括弧内に示されているアクション(または関数)のみが遅延します。 この例では、次のことが起こります。

  1. i = 1;
  2. 入力フィールドへの数値「1」の追加を0.9秒延期します。
  3. すぐにこの問題を設定した後、サイクルは続きます:i = 2;
  4. 入力フィールドへの数値「2」の追加を0.9秒延期します。

すぐにつまり、たとえば、1ミリ秒(つまり、900ミリ秒と比較して計り知れないほど小さい):サイクルはほぼ瞬時に作業を実行し、同じ時点からいくつかの保留中のタスクを作成します。 これは、保留中のすべての「描画」タスクが、新しい番号を追加する間に一時停止することなく、ほぼ同時に完了することを意味します。 サイクルが始まります。 すべてが0.9秒間フリーズします。 そしてshirrr-すべての数字が次々に連続して撃たれます。

そして、そのような場合、どのように適用するのが正しいのか setTimeout? それは複雑です。 関数を呼び出す必要があります 再帰的に(関数内から、同じ関数)、そしてこのプロセスが無限にならないように、停止条件(たとえば、出力された数値の値)を設定します。

関数welltest()(if(i< 9) { document.getElementById("test2").value += ++i window.setTimeout("welltest()", 400) } }

そして別の変数 関数の外部で初期化する必要があります-たとえば、次のようになります。

これで、すべてが正常に機能します(遅延時間を0.9秒から0.4秒に短縮しました)。 しかし、そのようなタスクでは、使用しない方が論理的です。 setTimeout NS setInterval(これには2つの関数が必要ですが):

関数besttest()(window.i = 0 window.timer1 = window.setInterval( "draw()"、400))function draw()(document.getElementById( "test3")。値+ = ++ i if(i > = 9)clearInterval(window.timer1))

Javascirptメソッドの機能 setInterval「単独で」通過しないという事実は、特別な方法で停止する必要があります clearInterval..。 そして、正確に何を停止するかを明確にするために、遅延アクションタスクには特別な識別子(タイマー)が割り当てられます:window.timer1 = window.setInterval(...)。

メソッドによって作成されたタスクに識別子を割り当てることもできます setTimeout..。 すべてのタイマーIDは互いに異なっている必要があります(現在のブラウザウィンドウ内で一意)。 次に、遅延アクションを使用するいくつかの異なるタスクをウィンドウで作成できます。これらのタスクは並行して実行されます(コンピューターに十分なリソースがある場合は、同時に実行されます)。これは、PHPやVBSでは基本的に不可能です。

複数のJavascriptタイマーが同時に実行されているページの例を次に示します:setinterval.htm(setinterval.jsファイル内のJavascript関数)。 Escキーを押すと、すべてのページタイマー(メニューを除く)の動作を停止できます。 すべてのサンプルタイマーは「自然」(抽象的ではない)に依存しています 私は++)カウントダウン-時間または距離。 すべての「クロック」は特別に非同期化されています(わかりやすくするため)。 距離ベースのタイマーは、「インジケーター」とプルダウン(プルダウン)メニューで使用されます。

ドロップダウンメニュー

私たちのプルアウトメニューは実際には(「ヘッダー」の下から)プルアウトです。要素間にギャップがあり、どのようにプルアウトされるかを確認します。 予期せぬことに、おそらくコンピューター(AMD Athlon 999 MHz)のパフォーマンスが低いために、さまざまな長さのリストに対して同じようにスムーズに終了できないことが判明しました。

美しさと調和のために、異なるメニュー項目のリストが同時に表示される必要があることは非常に明白です。 つまり、長いリストはより速いレートで、短いリストはより低いレートでドロップアウトする必要があります。 次のように実装できるようです。

  1. たとえば、「出発」の合計時間を200ミリ秒に設定します。
  2. ドロップダウンリストの高さが20ピクセルの場合、10ミリ秒で一度に1ピクセル下に移動できることは明らかです。その後、200ミリ秒でリスト全体がポップアップ表示されます。
  3. ドロップダウンの高さが40ピクセルの場合、同時に収まるようにするには、ドロップダウンを一度に1ピクセルずつ5ミリ秒で下に移動する必要があります。

このロジックによれば、ドロップダウンリストの高さが200ピクセルの場合、1ミリ秒で一度に1ピクセルずつ下に移動する必要があります。 しかし、この速度は私たちのコンピューターでは機能しません。ブラウザーには、リストの新しい位置を1ミリ秒で描画する時間がありません。 はい。 Javascriptには数える時間がありますが(数えるものは何ですか?)、ブラウザー(Firefox)には表示する時間がありません。 Webの典型的な状況。

したがって、松葉杖の助けを借りてのみメニューを離れる時間をほぼ均等にすることは可能であり、これがより高速なコンピューターでどのように機能するかはまだ不明です。 しかし、私たちは最も遅いものを頼りにしなければなりませんよね? アルゴリズム(コンピューターの速度を考慮しない場合)は、次のようになります。

  1. リストの合計チェックアウト時間を設定します:time = 224(ms)。
  2. サイクル内の1つの間隔の最小時間を設定します:delay = 3(ms)。
  3. リストを移動するための最小ステップを設定します:offset = 1(px)。
  4. リストの高さに応じて、これらすべてを変更します。1)遅延(間隔)時間を高さに反比例し、合計時間に正比例して増やします(高さ224の場合、係数は1です)。 2)高さが40ピクセルを超える場合は、高さに比例して最小ステップを増やします。 定数「40」は、最も遅いコンピューターで経験的に得られます。 Pentium 4 CPU 2.53GHzコンピューターでのテストでは、まったく同じ数(40)が明らかになりました。そうしないと、タイマーが暴走し、リストが追いつかなくなります。

現在、リストは多かれ少なかれ展開されています。 多かれ少なかれ同様の時間。 setinterval.htmページ。

そしてここにBru-mustacheがあります:

関数slide_do(obj、maxtop、offset)(if(getTopLeft(obj).top< maxtop) { obj.style.top = getTopLeft(obj).top + offset } else { if (obj && obj.timer1) { clearInterval(obj.timer1) obj.timer1 = null } } }

ネストされたリストをメニューから削除する関数自体は、ご覧のとおり、非常に単純です。 次のようなもので実行するだけです。

Ts.timer1 = setInterval(function()(slide_do(ts、maxtop、offset))、delay)

さて、始める前に、これらすべてのmaxtopとoffsetを計算し、リストをmintopの位置に配置します。 「予備」機能の機能 滑り台 ()サイズは40行。 そしてすべて一緒に-setinterval.jsファイルで。 はい、そしてこのがらくたは含まれているスタイルシートなしでは機能しません。