5秒待ってから次の行を実行する


313

以下のこの関数は、期待どおりに機能しません。JSの初心者なので、理由はわかりません。

かどうかを確認する前に5秒待つ必要newStateがあり-1ます。

現在、待機せず、ただちにチェックします。

function stateChange(newState) {
  setTimeout('', 5000);

  if(newState == -1) {
    alert('VIDEO HAS STOPPED');
  }
}

回答:


323

提供するコールバック関数にコードを配置する必要がありますsetTimeout

function stateChange(newState) {
    setTimeout(function () {
        if (newState == -1) {
            alert('VIDEO HAS STOPPED');
        }
    }, 5000);
}

他のコードはすぐに実行されます。


4
主な問題は、いくつかのケース(特にテスト)でこれがひどく不十分であることです。たとえば遅い非同期のhttpリクエストをシミュレートするために、関数から戻る前に500ミリ秒スリープする必要がある場合はどうなりますか?
A.Grandt

14
「テスト」とはユニットテストを意味します。テストフレームワークには、非同期テストを実行する方法が必要です。手動テストの場合:Chromeの[ネットワーク]タブには、遅いリクエストをシミュレートするスロットルドロップダウンがあります。
ジョセフSilber

1
Chrome拡張機能を開発し、注入されたスクリプトで最後に評価された値で結果が得られるとしたらどうでしょう。と私はいくつかの遅延が必要ですか?
mirek

184

本当にこれを行うべきではありません。タイムアウトの正しい使用は、OPの問題や、一定期間後に何かを実行したい場合に適したツールです。ジョセフ・シルバーは彼の答えでそれをよく示しています。ただし、本番以外のケースで本当に時間の期間、メインスレッドをハングアップしたい、これはそれを行います。

function wait(ms){
   var start = new Date().getTime();
   var end = start;
   while(end < start + ms) {
     end = new Date().getTime();
  }
}

次の形式で実行すると:

console.log('before');
wait(7000);  //7 seconds in milliseconds
console.log('after');

私がここに到着したのは、長時間実行するブロッキング操作(つまり、高価なDOM操作)に関連する非同期操作の混合をシーケンスするための簡単なテストケースを作成していて、これが私のシミュレートされたブロッキング操作だからです。それはその仕事にぴったりなので、私は同様のユースケースでここに到着した他の人にそれを投稿すると思いました。それでも、whileループでDate()オブジェクトを作成しているため、GCが十分に長く実行されると、GCを非常に圧倒する可能性があります。しかし、十分に強調することはできません。これはテストにのみ適しています。実際の機能を構築するには、Joseph Silberの回答を参照してください。


7
これはJavaScriptの実行を停止しません。
Terry Lin

23
@TerryLin実行してみてください。
マイク

6
つまり、基本的にはCPU時間を浪費しています。メインプロセッサが他のタスクに集中できるようにスレッドをスリープモードにしないので、これは待機ではありません。
Kyordhel 2017

6
@Gzorkスレッドのスリープは、待機関数を実装する1つの方法にすぎません。残念ながら、クライアント側のJavaScriptのコンテキストでは利用できません。ただし、クライアントの他の非同期タスクが実行中に完了すると考えている場合は、明らかにそれをテストしていません。私はメインスレッドで使用しますが、最初にsetTimeoutを介して呼び出された場合でも、他の非同期イベントjsfiddle.net/souv51v3/1に割り込む方法を示すフィドルを作成しました。 JSFiddleウィンドウ自体は、完了時に応答しなくなります。
マイク2017

1
ひどい解決策私見-それが「眠っている」間、CPUを独占します スリープ状態への正しい方法は、async / await alaを介して、この回答stackoverflow.com/questions/951021/…またはEtienneを経由することです。
David Simic

163

これは、新しいasync / await構文を使用したソリューションです。

これはECMAScript 6で導入された新機能なので、ブラウザーのサポートを確認してください。

効用関数:

const delay = ms => new Promise(res => setTimeout(res, ms));

使用法:

const yourFunction = async () => {
  await delay(5000);
  console.log("Waited 5s");

  await delay(5000);
  console.log("Waited an additional 5s");
};

このアプローチの利点は、コードが同期コードのように見え、動作することです。


ECMAScript 6は必要ありません:非同期読み込みを行うためにプロミスを既に使用していて、チェーンの一部を長時間かけて模倣したい場合は、このwait()関数をチェーンに追加できます。
Dovev Hefetz、2018

2
これは、新しい構文での最良の答えです。上記のwait()ソリューションの使用に問題がありました。
pianoman102


36

JavaScriptで5秒間一時停止しないでください。そのようには機能しません。コードの関数を5秒後に実行するようにスケジュールできますが、後で実行するコードを関数に入れ、その関数の残りのコードをすぐに実行し続ける必要があります。

例えば:

function stateChange(newState) {
    setTimeout(function(){
        if(newState == -1){alert('VIDEO HAS STOPPED');}
    }, 5000);
}

しかし、次のようなコードがある場合:

stateChange(-1);
console.log("Hello");

console.log()文はすぐに実行されます。stateChange()関数でタイムアウトが発生するまで待機しません。JavaScriptの実行を所定の時間だけ一時停止することはできません。

代わりに、遅延を実行するコードは、setTimeout()コールバック関数内にある(またはその関数から呼び出される)必要があります。

ループによって「一時停止」しようとした場合、基本的にはJavaScriptインタープリターを一定期間「ハング」させます。JavaScriptはコードを1つのスレッドでのみ実行するため、ループしているときは他に何も実行できません(他のイベントハンドラーを呼び出すことはできません)。したがって、変数が変更されるのを待ってループすることは、その変数を変更するために他のコードを実行できないため、機能しません。


31
JavaScriptの実行を所定の時間だけ一時停止することはできません。次のことができるので、あなたはそうすべきではないと思います:(自分でvar t = new Date().getTime(); while (new Date().getTime() < t + millisecondsToLockupBrowser);

9
@JosephSilber-わかりました。そうすることはできますが、実際には機能しません。多くのブラウザでは、スクリプトが応答しなくなったことを示すダイアログが表示され、ユーザーエクスペリエンスがひどく、バッテリーの寿命が長く、ページがそうしている間にぶら下がって…それは悪いだろう。
jfriend00

12
まあ当然の恐ろしいだろう、と誰もがなければならない今まで、これまで史上かつて史上かつてないこともしません。私は自分の内面を「実際に」抵抗することができませんでした。ごめんなさい。
ジョセフSilber 2013年

31

あなたがいる場合は、非同期機能は、単に1行でそれを行うことができます。

console.log(1);
await new Promise(resolve => setTimeout(resolve, 3000)); // 3 sec
console.log(2);

お知らせ、ターゲットがNodeJSであれば、これを使用する方が効率的になります(それが事前に定義promisified setTimeout関数です):

await setTimeout[Object.getOwnPropertySymbols(setTimeout)[0]](3000) // 3 sec

2つの実装の違いは何ですか?
EAzevedo

1
現在、違いはありません。しかし、ある時点でノードがそれをより速く/より安全に/より効率的にすることを決定する場合、ノードのjsバージョンを前もって使用することになります。読みやすさはほとんどの人にとって重要な要素である可能性が高いですが、その場合は、最初の方法を使用するほうがよいでしょう。
Shl

ありがとうございました。あなたの答えは、私がすでに3日間直面している問題を解決しました。ありがとう。
EAzevedo

8

これを試して:

//the code will execute in 1 3 5 7 9 seconds later
function exec() {
    for(var i=0;i<5;i++) {
        setTimeout(function() {
            console.log(new Date());   //It's you code
        },(i+i+1)*1000);
    }
}

7

ミリ秒単位で待機するこのような関数を作成する最良の方法です。この関数は、引数で指定されたミリ秒待機します。

function waitSeconds(iMilliSeconds) {
    var counter= 0
        , start = new Date().getTime()
        , end = 0;
    while (counter < iMilliSeconds) {
        end = new Date().getTime();
        counter = end - start;
    }
}


3

ジョセフ・シルバーの答えに基づく、私はそのようにします、もう少し一般的です。

あなたはあなたの機能を持っています(質問に基づいて作成しましょう):

function videoStopped(newState){
   if (newState == -1) {
       alert('VIDEO HAS STOPPED');
   }
}

そして、あなたは待機機能を持つことができます:

function wait(milliseconds, foo, arg){
    setTimeout(function () {
        foo(arg); // will be executed after the specified time
    }, milliseconds);
}

最後に、次のようになります。

wait(5000, videoStopped, newState);

それは解決策です、私はむしろウェイト関数で引数を使用しないでください(foo();代わりにを持つだけですfoo(arg);)が、それは例のためです。



1

関数(asyncとawait)に小さな変更を加えることで、遅延を追加できます。

const add5SecondsDelay = () => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('5 seconds');
    }, 50000);
  });
}

async function asyncFunctionCall() {

  console.log("stpe-1"); 
  const result = await add5SecondsDelay ();
  console.log("step-2 after 5 seconds delay"); 

}

asyncFunctionCall();

-2

angularjsを使用して:

$timeout(function(){
if(yourvariable===-1){
doSomeThingAfter5Seconds();
}
},5000)

-2

新しいJs関数を作成する

function sleep(delay) {
        var start = new Date().getTime();
        while (new Date().getTime() < start + delay);
      }

実行を遅らせたいときに関数を呼び出します。遅延値にはミリ秒をintで使用します。

####Some code
 sleep(1000);
####Next line

3
これはリソースを大量に消費します。
awavi

-2

エッジまたはIEからPCゲームを実行するために使用しました。そして、7秒後にIE Edgeを自動的に閉じます。

FirefoxとGoogle Chromeを使用して、この方法でゲームを開始することはできません。

<html<body>
<a href="E:\game\game.exe" name="game" onmouseout="waitclose(7000);"> game
<img src="game.jpg" width="100%" height="97%" ></a>
<script>
function waitclose(ms){
 var start = new Date().getTime();var end=start;
 while(end < start + ms) {end = new Date().getTime();}
window.open('', '_self', ''); window.close();
}
</script>
</body></html>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.