sleep()のJavaScriptバージョンは何ですか?


2335

sleepJavaScriptでa を作成するには、次のpausecomp関数(ここから取得)よりも優れた方法がありますか?

function pausecomp(millis)
{
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < millis);
}

これはJavaScriptスリープの複製ではありません-アクション間の遅延。コードの一部が実行される前の遅延ではなく、関数の真ん中で実際のスリープが必要です。


4
それはしばらくの間に設定することです、私がsetTimeoutを使用する場合、whileは引き続き処理され、さらに多くのsetTimeoutsをキューに入れ、最終的に同時に実行され、それらの間で少し並行性を作ります
fmsf

160
これは恐ろしい解決策です。何もせずに処理サイクルを増やしてしまうでしょう。

12
スリープの唯一の目的は、ポーリングまたはコールバックの待機です-setIntervalとsetTimeoutはどちらもこれよりも優れています。
アナカタ09年

1
おそらくあなたはJavaScriptの継続渡しスタイルであなたが望むことをすることができます。見てみましょうこの記事を。
Ognyan Dimitrov

回答:


2563

2017年-2019年更新

この質問が行われた2009年以降、JavaScriptは大幅に進化しました。他のすべての回答は廃止されたか、過度に複雑になりました。現在のベストプラクティスは次のとおりです。

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function demo() {
  console.log('Taking a break...');
  await sleep(2000);
  console.log('Two seconds later, showing sleep in a loop...');

  // Sleep in loop
  for (let i = 0; i < 5; i++) {
    if (i === 3)
      await sleep(2000);
    console.log(i);
  }
}

demo();

これだよ。await sleep(<duration>)

またはワンライナーとして:

await new Promise(r => setTimeout(r, 2000));

ご了承ください、

  1. awaitasyncキーワードが前に付いている関数でのみ、または一部の環境(例:Chrome DevToolsコンソール、Runkit)のスクリプトの最上位で実行できます。
  2. await現在のasync機能のみを一時停止します

2つの新しいJavaScript機能がこの「スリープ」関数の作成に役立ちました。

互換性

何らかの奇妙な理由で7より古いノード(サポート終了に達した)を使用している場合、または古いブラウザーをターゲットにしている場合、async/ awaitBabel(JavaScript +新機能を単純な古いJavaScriptに変換するツール)を介して引き続き使用できます。 、transform-async-to-generatorプラグイン付き。


5
ここで素晴らしいもの。JSが「スリープ」モードを呼び出した後、これは最近のブラウザーの「アクティブ」/「非アクティブ」状態にどのように影響または関連するのでしょうか。ブラウザは、一般的なJSで期待されるようにスリープをブロックして、後で「アクティブ」になったときにリコールすることができますか、それとも別の動作をしますか?
Andre Canilho 2016年

18
これに対する現在のブラウザーサポートは何ですか?このソリューションが大多数のブラウザー、または少なくともすべての一般的なブラウザーでサポートされるまで、私は以前のソリューションが「時代遅れ」であるとは考えません。それどころか、このソリューションは興味深いものですが、広くサポートされるまでは使用できない/実用的ではないと考えます。
Alvin Thompson

75
これは「本当の睡眠」ではなく、質問の答えにはなりません。質問者は、stackoverflow.com / questions / 758688 / sleep-in-javascriptと彼の質問を明確に区別しました。実際のスリープ状態では、他のコードは実行できません(他のスレッドでない限り)。この回答は他の質問に適しています。
niry 2017年

4
@jacroe-トランスパイラーは、矢印機能と非同期/待機(IEがとにかく血を吐く原因となる)を処理します
Jaromanda X

11
@niry JavaScriptはシングルスレッド言語であるため、UIと同じスレッドで実行され、Webページが応答しなくなるため、「実際の」スリープにはあまり適していません。
パトリックロバーツ

849

2016年最新の回答を参照してください)

アクションを実行し、待機してから、別のアクションを実行することは、完全に合理的だと思います。マルチスレッド言語での記述に慣れている場合は、おそらくスレッドが起動するまでの一定時間実行を放棄するという考えがあるでしょう。

ここでの問題は、JavaScriptがシングルスレッドのイベントベースのモデルであることです。特定のケースでは、エンジン全体を数秒間待機させるのは良いことかもしれませんが、一般的には悪い習慣です。私が自分の関数を書きながら関数を利用したいと思いますか?私があなたのメソッドを呼び出したとき、私のメソッドはすべてフリーズしました。JavaScriptが何らかの形で関数の実行コンテキストを保持し、どこかに保存し、それを元に戻して後で続行できる場合、スリープが発生する可能性がありますが、それは基本的にスレッド化です。

そのため、他の人が提案したことにかなりこだわっています。コードを複数の関数に分割する必要があります。

それであなたの質問は少し間違った選択です。あなたが望む方法で眠る方法はありませんし、あなたが提案する解決策を追求すべきではありません。


45
これは正解ではありません。JavaScriptにスリープ機能がない場合、それはECMAScriptがそれを必要としないためです。これは、Javascriptの設計を担当する団体による設計の選択です。Javascriptランタイムが次のコード行を実行する前に一定の時間待機するようにできた可能性がありますが、そうしないように選択されました。
Didier A.

5
スリープは、リアルタイムの精度ではありませんが、JavaScriptで完全に実装できます。結局のところ、それはイベントベースのシステムです。非同期呼び出しが完了すると、イベントがトリガーされます。sleep()が発行された後、スリープが終了するまでブラウザーに制御が戻り、呼び出し元の関数に制御が戻る場合、同じことができない理由はありません。そして、はい、特に、開発者がデザインを台無しにする前に、開発者が設計をひどく悪くする前に、時間のない完全なリファクタリング以外に方法がない場合、スリープが便利であることに同意します
Lawrence

このアイデアに従うHypnoticを試してください:coolwanglu.github.io/hypnotic/web/demo.html
Tezcat

4
シングルスレッドのjavascriptを呼び出すことは、神話にすぎません。技術的には正しいかもしれませんが、機能的にはマルチスレッド言語のように動作します。fork()のシミュレーションは非常に簡単で、yield()は実際には実装できませんが、共有メモリを使用してロック/セマフォを実行することで、かなり接近できます。平均的なプログラマにとって、マルチスレッドとして扱うことは理にかなっています。技術的な名前は言語の開発者にとってのみ重要です。
Benubird、2015年

8
sleep()JSではそれが不可能であり、ほとんどの場合、より適切な方法があることに同意します。しかし、エンジンがすべてのものを結び付ける方法は、まだ設計上の欠陥であると考えています。言語がsleep()特定のスクリプト、ページ、またはエンジンがCPUを破壊し、マニアックのようにアプリをフリーズせずに機能を制限できない理由はありません。それは2015年であり、Webブラウザ全体をでクラッシュさせることはできませんwhile(1)。そのようなことのためのフラッシュがあります。
Beejor

660

JavaScriptでは、すべての関数を書き換えて、できるだけ早く終了できるようにします。DOMを変更できるように、ブラウザーを制御できるようにしたいとします。

関数の途中でスリープ状態にする必要があるたびに、を使用するようにリファクタリングしましたsetTimeout()

編集する

悪名高い睡眠、または遅延は、どの言語でも機能するかについては、多くの議論があります。特定の機能を起動するためのシグナルまたはコールバックが常に必要であると言う人もいれば、任意の遅延時間が役立つと主張する人もいます。私は、彼ら自身と1つのルールがこの業界で何かを指示することは決してできないと言います。

スリープ関数の記述は簡単で、JavaScript Promisesでさらに使いやすくなっています。

// sleep time expects milliseconds
function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// Usage!
sleep(500).then(() => {
    // Do something after the sleep!
});

190
閉鎖によって。 function foobar(el) { setTimeout(function() { foobar_cont(el); }, 5000); }
カオス

68
わかりました。コードがWebページでの使用を意図していない場合はどうなりますか?
EugenioMiró

10
@EugenioMiróコードがWebページでの使用を意図していない場合は、ホストのオブジェクトモデルにスリープメソッドを実装させます。-この質問は、Webページで実行されているJavaScriptに公開されているDOMに向けられていると思います。
BrainSlugs83 '24

31
@Nosrednaはい、非同期呼び出しの方法を理解しています。これは、sleep()の助けにはなりません。呼び出しを特定の順序で行い、データを特定の順序に戻したい。forループの深さは5レベルです。実行をブロックしたい。真のスリープメソッドは「ブラウザーの速度を落とす」ことはありません。スリープハンドは、ブラウザーと、まだブロックしている間にCPU時間を必要とする他のスレッドに制御を戻します。
BrainSlugs83 '24

382
これは質問に対する答えではありません。
TMS

303

debug / devの場合のみ、誰かに役立つ場合はこれを投稿します

興味深いもの、Firebug(およびおそらく他のjsコンソール)では、Enterキーを押した後は何も起こりません。指定されたスリープ期間の後だけです(...)

function sleepFor( sleepDuration ){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ /* do nothing */ } 
}

使用例:

function sleepThenAct(){ sleepFor(2000); console.log("hello js sleep !"); }

36
これは答えではありません。質問のコードとまったく同じですが、少し短いだけです。
jab

16
忙しいのは本当に?JSでは?何秒?これをしているウェブサイトを見つけたら、ブロックされます。
mafu

35
@mafuだからこそ、only for debug/dev... rolleyes
xDaizu

12
これは絶対に行わないでください。これにより、CPUは実行するコアを100%ヒットさせ、ブロックします。
noego

3
async / awaitは役に立たないため、これは便利であり、おそらくコマンドラインJavaScriptアプリケーション内でスリープする唯一の方法です。
Wheezil 2018年

177

私は他のポスターに同意します、忙しい睡眠はちょうど悪い考えです。

ただし、setTimeoutは実行を保留せず、タイムアウトが設定された直後に関数の次の行を実行します。タイムアウトが経過した後ではありません。そのため、スリープと同じタスクは実行されません。

これを行う方法は、関数を前と後の部分に分解することです。

function doStuff()
{
  //do some things
  setTimeout(continueExecution, 10000) //wait ten seconds before continuing
}

function continueExecution()
{
   //finish doing things after the pause
}

関数名が各部分の動作を正確に説明していることを確認します(funcPart1およびfuncPart2ではなく、IE GatherInputThenWaitおよびCheckInput)。

編集する

この方法は、タイムアウト後まで決定したコード行を実行せずに、クライアントPCに制御を戻して、キューに入れられた他のすべてを実行するという目的を達成します。

さらに編集

コメントで指摘されているように、これはループではまったく機能しません。奇妙な(醜い)ハッキングを行ってループで動作させることもできますが、一般的には悲惨なスパゲッティコードになります。


12
うん。これがトリッキーになるのは、ループがある場合、またはネストされたループがある場合です。forループを放棄し、代わりにカウンターを用意する必要があります。
Nosredna

Touché。つまり、それはまだ可能ですが、その場合は醜くハックです。いくつかの静的ブール状態変数を使用することもできますが、これもかなりハックです。
DevinB 2006年

2
-1。繰り返しますが、これは質問の答えにはなりません。これは、「コードの実行をブロックする方法」とは大きく異なる「関数を非同期に実行する方法」のような質問に対する回答です。
Deepak GM

6
@Nosrednaいいえ、クロージャーを使用します。例: function foo(index) { setTimeout(function() { foo_continue(index); }, 10000); }and for(var X = 0; X < 3;X++) { foo(X); }- X のがに渡されfoo、最終的にが呼び出されたindexときに、その名前で再利用さfoo_continueれます。
イズカタ2014年

2
@Alexanderもちろん、そうです。setTimeout()の目的は、コードを非同期で実行することによってブラウザがロックアップするのを防ぐことです。入れてconsole.log()内部をfoo_continue()setTimeoutをバージョンでは、あなたは同じ結果を得ます。
イズカタ2015年

132

$ DEITYが大好きなため、ビジー待機スリープ機能を作成しないでください。 setTimeoutそしてsetIntervalあなたが必要とするすべてを行います。

var showHide = document.getElementById('showHide');
setInterval(() => {
    showHide.style.visibility = "initial";
    setTimeout(() => {
        showHide.style.visibility = "hidden"
    }, 1000);
    ;
}, 2000);   
<div id="showHide">Hello! Goodbye!</div>

2秒ごとに1秒間テキストを非表示にします。これは、setIntervalおよびsetTimeoutを使用して、毎秒テキストを表示および非表示にする方法を示しています。


3
すべてがうまくいくわけではありません。setIntervalはポーリングの印象を大幅に改善します。
アナカタ09年

3
そのコード部分がJavaScriptエンジンで妨げられないものは何でしょうか?
Deniz Dogan

10
スリープを同期させる必要がない限り、これは完全に有効な質問です。
アーロンデュフォー

36
私たちの多くは、JavaScriptがブラウザーのみの言語ではないことを忘れているかもしれません。この男は、setTimeoutに伴うすべての変数スコープの問題に対処する必要なしに、短い休止を必要とするNodeコマンドラインユーティリティを作成している可能性があります。
Phil LaNasa、2014年

3
@PhilLaNasa:構文閉鎖はまだ1、真剣にノード101を介して気合いと作業する必要が1をギョッされた場合
混沌

113

私はこれが少し古い質問であることを知っていますが、(私のように)RhinoでJavascriptを使用している場合は、使用できます...

try
{
  java.lang.Thread.sleep(timeInMilliseconds);
}
catch (e)
{
  /*
   * This will happen if the sleep is woken up - you might want to check
   * if enough time has passed and sleep again if not - depending on how
   * important the sleep time is to you.
   */
}

4
これはJavaの呼び出しですか?
Ken Sharp

14
これはJavascript ではなくJavaです
RousseauAlexandre

18
@RousseauAlexandre不正解です。これは、Rhinoを使用したJavaScriptです(現時点では、最近ではNashorn
でもかまいません

71

jQueryを使用している場合、誰かが実際にsetTimeoutのラッパーにすぎない「遅延」プラグインを作成しました。

// Delay Plugin for jQuery
// - http://www.evanbot.com
// - © 2008 Evan Byrne

jQuery.fn.delay = function(time,func){
    this.each(function(){
        setTimeout(func,time);
    });

    return this;
};

その後、期待どおりに関数呼び出しの行でそれを使用できます。

$('#warning')
.addClass('highlight')
.delay(1000)
.removeClass('highlight');

4
それは悪い解決策ではありません。コンテキストと連鎖性を保持します。
Nosredna 2009年

39
jQuery 1.4以降、.delay()はjQueryの一部です(ただし、セマンティクスは上記の実装とは異なります)。api.jquery.com/delay
Matt Ball

7
この質問に明らかに欠けていたのは、jQueryの回答でした。とても嬉しいです!
xDaizu 2016

1
2つの独立した呼び出しの間に遅延が必要な場合は、そうです。ループを遅くするために遅延が必要な場合は、必要ありません。
WGroleau 2018年

46

私もスリープソリューションを検索しました(製品コードではなく、開発/テストのみ)。この記事を見つけました。

http://narayanraman.blogspot.com/2005/12/javascript-sleep-or-wait.html

...そしてここにクライアント側のソリューションとの別のリンクがあります:http : //www.devcheater.com/

また、を呼び出すとalert()、アラートが表示されている間、コードも一時停止されます。アラートを表示せずに同じ効果を得る方法を見つける必要があります。:)


35
多くの人が「いいえ、製品コードではこれを行わないでください!」と言っています。ええ、ええと、私はしたくないです。私は使い捨てのテストコードでそれをしたいので、エレガントなソリューションを作るのに多くの時間を費やしたくありません。
user435779 2012年

31

次に、同期XMLHttpRequestを使用した簡単なソリューションを示します。

function sleep(n){
  var request = new XMLHttpRequest();
  request.open('GET', '/sleep.php?n=' + n, false);  // `false` makes the request synchronous
  request.send(null);
}

sleep.phpの内容:

<?php sleep($_GET['n']);

今度は次のように呼び出します:sleep(5);


5
@lukad、setTimeout()それが機能する場合に使用しますが、それが1000行のコールバックを解明することを意味する場合、これは冗談のように見えなくなる可能性があります。
pguardiario 2014

11
ユニークなアプローチですが、残念ながら非同期ではないXMLHttpRequestsは非推奨であり、将来的には削除される予定です。そもそも面白いのは、その事実が私をこの質問に最初に導いた理由です。
Beejor

これは実際にはかなり良いアイデアのIMOです。スリープAPI(リクエストURL)は悪用される可能性があるため、公開すべきではないと思います。
Vahid Amiri、2016年

@Beejorは常に未来についてのみ考えるということは、未来の非現実性に生きることを意味します:-)
user1742529

いいですが、インターネットが遅い場合や、Webサイトのping時間がスクリプトのスリープ時間よりも長い場合は、引数の時間以上かどうかを知っていますか。使用sleep(300)してウェブサイトの応答に150ミリ秒かかる場合と同様に、JavaScriptコードは450ミリ秒スリープします。また、ブラウザによってインターネット接続が失われた場合、0ミリ秒しか機能しません。したがって、それは良い解決策ではありません
H Chauhan

30

どうぞ。コードが言うように、悪い開発者にならないで、これをウェブサイトで使用してください。開発ユーティリティ機能です。

// Basic sleep function based on ms.
// DO NOT USE ON PUBLIC FACING WEBSITES.
function sleep(ms) {
    var unixtime_ms = new Date().getTime();
    while(new Date().getTime() < unixtime_ms + ms) {}
}

17
これは基本的にOPと同じです。
アンドリューバーバー、

5
より正確には、それはOPが代替を要求したものです。
WGroleau 2018年

解決策は適切ではありませんが、一部の地域async/awaitでは残念ながら応答が悪く、強制的に使用する必要があります。
Nabi KAZ

21

私は個人的にシンプルなものが好きです:

function sleep(seconds){
    var waitUntil = new Date().getTime() + seconds*1000;
    while(new Date().getTime() < waitUntil) true;
}

次に:

sleep(2); // Sleeps for 2 seconds

P5jsでスクリプトを作成する際に偽のロード時間を作成するために常にそれを使用しています


3
私はこれを主な質問の最も最適化されたバージョンだと考えています。ループ内では計算を行わず、単なる比較です。それを読むのは少し難しいです。
hegez

4
絶対にしないでください。この機能の動作中にCPU使用率を確認しましたか?十分な時間をかければ、100%に近いはずです。
noego 2017

2
@hegez:ループが何に関係なく一定のウォールクロック時間実行されることを考えると、ループの最適化は要点のようなもののようです。
ShadowRanger 2018

@noegoどうやって?ノード10でテストしたところ、CPU使用率の変更はまったくありません
melMass

@melMassこの関数は、CPUを100%ビジー状態に保つことにより、ノードスレッドをn秒間ブロックするだけです。この「解決策」は、これら2つの理由(ブロッキング+ CPUキラー)のために非常に悪い考えです。HASが非ブロッキングになるのを待機しているため、非同期です。
Jeremy Thille

20

最初:

次のように、実行する関数を定義します。

function alertWorld(){
  alert("Hello World");
}

次に、setTimeoutメソッドを使用してその実行をスケジュールします。

setTimeout(alertWorld,1000)

2つのことに注意してください

  • 2番目の引数はミリ秒単位の時間です
  • 最初の引数として、括弧なしで関数の名前(参照)のみを渡す必要があります


18

物事をほとんどの人が望むものに見せるためのより良い解決策は、匿名関数を使用することです:

alert('start');
var a = 'foo';
//lots of code
setTimeout(function(){  //Beginning of code that should run AFTER the timeout
    alert(a);
    //lots more code
},5000);  // put the timeout here

これは恐らくあなたが単にあなたが望むことをする何かに到達する最も近いものです。

複数のスリープが必要な場合、これは急いで醜くなる可能性があり、実際に設計を再考する必要がある場合があります。


これは、デスクトップブラウザーと古い携帯電話で私のために働いたものです。私が試した他のものはすべてにうまくいきませんでした。
マイク

10

ブラウザーに関しては、setTimeoutとsetIntervalを使用する方法に同意します。

ただし、サーバー側コードの場合は、ブロッキング関数が必要になる場合があります(たとえば、スレッドの同期を効果的に行うことができます)。

node.jsとmeteorを使用している場合、ファイバーでsetTimeoutを使用する際の制限に直面している可能性があります。サーバー側のスリープのコードは次のとおりです。

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

参照:https : //github.com/laverdet/node-fibers#sleep


Server may require a blocking function... Nodeの唯一のスレッドを強力にブロックし、サーバー全体が数秒間応答しないようにするのは良い考えではありませんが、何でも
Jeremy Thille

10

他の非同期タスクとコードの整合性を保つために、setTimeOutをPromiseにカプセル化します:Demo in Fiddle

function sleep(ms)
{
    return(new Promise(function(resolve, reject) {        
        setTimeout(function() { resolve(); }, ms);        
    }));    
}

そのように使用:

sleep(2000).then(function() { 
   // Do something
});

Promiseを使用していた場合、構文を覚えやすくなります。


4
なぜこれは単にsetTimeout(function(){/ * do something * /}、2000);を使用するよりも優れているのですか?
JSideris 2016年

10

Atomics.waitを使用した2019アップデート

ノード9.3以降で動作するはずです。

Node.jsにはかなり正確なタイマーが必要でしたが、そのためにうまく機能しました。ただし、ブラウザのサポートは非​​常に限られているようです。

let ms = 10000;
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);

いくつかの10秒タイマーベンチマークを実行しました。

setTimeoutを使用すると、最大7000マイクロ秒のエラーが発生します。(7ms)

Atomicsを使用すると、私のエラーは600マイクロ秒未満に留まるようです。(0.6ms)

2020年の更新:まとめ

function sleep(millis){ // need help of a server-side page
  let netMillis=Math.max(millis-5,0); //assuming 5ms overhead
  let xhr=new XMLHttpRequest();
  xhr.open('GET','/sleep.jsp?millis='+netMillis+'&rand='+Math.random(), false);
  try{
    xhr.send();
  }catch(e){
  }
}
function sleepAsync(millis){ // use only in async function
  let netMillis=Math.max(millis-1,0); // assuming 1ms overhead
  return new Promise((resolve)=>{
    setTimeout(resolve, netMillis);
  });
}
function sleepSync(millis){ // use only in worker thread, currently Chrome-only
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, millis);
}

function sleepTest(){
  console.time('sleep');
  sleep(1000);
  console.timeEnd('sleep');
}
async function sleepAsyncTest(){
  console.time('sleepAsync');
  await sleepAsync(1000);
  console.timeEnd('sleepAsync');
}
function sleepSyncTest(){ 
  let source=`${sleepSync.toString()}
    console.time('sleepSync');
    sleepSync(1000);
    console.timeEnd('sleepSync');`;
  let src='data:text/javascript,'+encodeURIComponent(source);
  console.log(src);
  var worker=new Worker(src);
}

サーバーサイドのページ、例えばsleep.jsp

<%
try{
  Thread.sleep(Long.parseLong(request.getParameter("millis")));
}catch(InterruptedException e){}
%>

私の意見では、呼び出し側で非同期/待機なしに単純な関数として実装できない、受け入れられているソリューションよりも優れています。
GroovyDotCom

ええ、これがブロックしていることと、通常はそれが良いことではないことに気づいている限り
Kapytanhook

かっこいいですが、これはChromeとFirefoxでのみサポートされているため、Webでの使用にはあまり適していません。(2019年11月)
JGreatorex

9

ここでの答えのほとんどは、見当違いであるか、少なくとも時代遅れです。javascriptをシングルスレッドにする必要がある理由はありませんし、実際にそうする必要もありません。今日では、すべての主流のブラウザーがワーカーをサポートしています。これが実現する前は、RhinoやNode.jsなどの他のJavaScriptランタイムがマルチスレッドをサポートしていました。

「JavaScriptはシングルスレッドです」は有効な答えではありません。たとえば、ワーカー内でスリープ関数を実行しても、UIスレッドで実行されているコードはブロックされません。

ジェネレーターとyieldをサポートする新しいランタイムでは、シングルスレッド環境でスリープ機能に同様の機能を提供できます。

// This is based on the latest ES6 drafts.
// js 1.7+ (SpiderMonkey/Firefox 2+) syntax is slightly different

// run code you want to sleep here (ommit star if using js 1.7)
function* main(){
    for (var i = 0; i < 10; i++) {
        // to sleep for 10 milliseconds 10 times in a row
        yield 10;
    }

    yield 5;
    console.log('I just slept 5 milliseconds!');
}

// resume the given generator after ms milliseconds
function resume(ms, generator){
    setTimeout(function(){
        // ommit .value if using js 1.7
        var nextSleep = generator.next().value;
        resume(nextSleep, generator);
    }, ms);
}

// initialize generator and get first sleep for recursive function
var
    generator = main(),
    firstSleep = generator.next().value;

// initialize recursive resume function
resume(firstSleep, generator);

このスリープの模倣は、スレッドをブロックしないため、真のスリープ機能とは異なります。これは、JavaScriptの現在のsetTimeout関数の上にある単なる砂糖です。この機能タイプはTask.jsに実装されており、現在Firefoxで機能するはずです。


少なくともバージョン10までは、ワーカーはIEに実装されていません。現在、大量のユーザーを表しています。
Beejor

確かに、それでも、sleep複数のワーカーを使用して実装することは現実的ではありません。Node.jsジェネレーター機能を使用している場合は、すでに実装されており、説明どおりに使用できます。現在、主流のブラウザーにはジェネレーターがすべて実装されているわけではありません。
Gabriel Ratener、

8

私はjavascript sleep / waitでかなりの数のWebページを検索/グーグルで検索しましたが、javascriptを「RUN、DELAY、RUN」にしたい場合、答えはありません...ほとんどの人が得たものは、「RUN、RUN(役に立たないもの)、RUN」または「RUN、RUN +遅延実行」....

だから私はいくつかのハンバーガーを食べて考えました:::これは機能する解決策です...しかし、実行中のコードを選択する必要があります... :::はい、私は知っています、これはリファクタリングを読むのがもっと簡単です... 。まだ...

// ......................................... // example1:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setInterval
var i = 0;

function run() {
    //pieces of codes to run
    if (i==0){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==1){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i >2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" is ran</p>"; }
    if (i==5){document.getElementById("id1").innerHTML= "<p>all code segment finished running</p>"; clearInterval(t); } //end interval, stops run
    i++; //segment of code finished running, next...
}

run();
t=setInterval("run()",1000);

</script>
</body>
</html>

// .................................... // example2:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout
var i = 0;

function run() {
    //pieces of codes to run, can use switch statement
    if (i==0){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(1000);}
    if (i==1){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(2000);}
    if (i==2){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>"; sleep(3000);}
    if (i==3){document.getElementById("id1").innerHTML= "<p>code segment "+ i +" ran</p>";} //stops automatically
    i++;
}

function sleep(dur) {t=setTimeout("run()",dur);} //starts flow control again after dur

run(); //starts
</script>
</body>
</html>

// ................. example3:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout
var i = 0;

function flow() {
    run(i);
    i++; //code segment finished running, increment i; can put elsewhere
    sleep(1000);
    if (i==5) {clearTimeout(t);} //stops flow, must be after sleep()
}

function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==1){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
}

function sleep(dur) {t=setTimeout("flow()",dur);} //starts flow control again after dur

flow(); //starts flow
</script>
</body>
</html>

// .............. example4:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
//javascript sleep by "therealdealsince1982"; copyrighted 2009
//setTimeout, switch
var i = 0;

function flow() {
    switch(i)
    {
        case 0:
            run(i);
            sleep(1000);
            break;
        case 1:
            run(i);
            sleep(2000);
            break;
        case 5:
            run(i);
            clearTimeout(t); //stops flow
            break;
        default:
            run(i);
            sleep(3000);
            break;
    }
}

function run(segment) {
    //pieces of codes to run, can use switch statement
    if (segment==0){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==1){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment==2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
    i++; //current segment of code finished running, next...
}

function sleep(dur) {t=setTimeout("flow()",dur);} //starts flow control again after dur

flow(); //starts flow control for first time...
</script>
</body>
</html>

5
OK、これはsetTimeputで機能しますが、何が起こっているのかを確認するのは困難です。setTimeout自体の使用は、これよりも簡単です。
naugtur

7
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

本当の質問と同じです。それを本当の答えにするのはあまり意味がありません。
EML 2014年

2
良い解決策ではありません-SeleniumのJavaScriptExecutorでこれを使用すると、2104 MacBook ProでChromeブラウザが約50%の時間ハングします。
エメリー、2015年

7

依存関係のない最短のソリューション:

await new Promise(resolve => setTimeout(resolve, 5000));

IE11では動作しません。アロー関数の構文エラーが発生しました。
DDphp

@ Java-DKの使用await new Promise(function(resolve) { setTimeout(resolve, 5000); });
k06a

6

JavaScriptでそのようなスリープを行うことはできません。むしろ、すべきではありません。sleepまたはwhileループを実行すると、ループが完了するまでユーザーのブラウザーがハングします。

参照したリンクで指定されているタイマーを使用します。


6

setTimeout()を使用するのではなく、sleep()関数が必要になるシナリオの1つは、ユーザーのクリックに応答する関数があり、最終的に新しいIEポップアップウィンドウを開いて、短時間の処理を開始した場合です。ポップアップが表示される前に完了します。開いているウィンドウをクロージャに移動すると、通常はブラウザによってブロックされます。


6

同期実行に対応する必要がある場合、スリープ関数の目的を理解できます。setInterval関数とsetTimeout関数は、実行シーケンスをメインプログラムに戻す並列実行スレッドを作成します。これは、特定の結果を待つ必要がある場合には無効です。もちろん、イベントやハンドラーを使用することもできますが、意図されていない場合もあります。


6

私の2つのビットを追加します。テストのために忙しい待ち時間が必要でした。コードを分割したくなかったので、多くの作業が必要だったので、簡単に分割できました。

for (var i=0;i<1000000;i++){                    
     //waiting
  }

これを行うことの欠点は見当たらず、それは私にとってはトリックでした。


コンパイルされる可能性があります。
Viktor Sehr 2013

このようにしないでください。これはブロッキングスリープコールです。つまり、コードがJSスレッドを占有している間は他のJavaScriptを実行できません。
Steve Midgley、2014年

5
@SteveMidgley「あなたのコードがJSスレッドを独占している間、他のjavascriptは実行できません」というのは、OPがやりたいこととまったく同じです¯_(ツ)_ /
¯– drigoangelo

1
私はいくつかのテストを実行したところ、空のループでもブラウザとCPU(JavaScriptだけでなく)がブロックされるようです。また、forループの使用は、の最大値に関係なく、またi内部に配置された複雑な数学コードを使用しても、ほとんど常に即座に実行されます。したがって、数ミリ秒しか待機していない限り、JSで優雅にスリープする方法はまだないようです。
Beejor

100万は大きすぎます。私にとっては十分な1万
Vlad

6

これは、Javaのsleepメソッドを使用して行うことができます。私はそれをFFとIEでテストしましたが、コンピューターをロックしたり、リソースを消費したり、無限のサーバーヒットを引き起こしたりしません。私にはクリーンなソリューションのようです。

まず、ページにJavaをロードして、そのメソッドを使用可能にする必要があります。それをするために、私はこれをしました:

<html>
<head>

<script type="text/javascript">

  function load() {
    var appletRef = document.getElementById("app");
    window.java = appletRef.Packages.java;
  } // endfunction

</script>

<body onLoad="load()">

<embed id="app" code="java.applet.Applet" type="application/x-java-applet" MAYSCRIPT="true" width="0" height="0" />

次に、JSで簡単な一時停止が必要な場合に実行する必要があるのは次のとおりです。

java.lang.Thread.sleep(xxx)

ここで、xxxはミリ秒単位の時間です。私の場合(正当化のため)、これは非常に小さな会社でのバックエンド注文処理の一部であり、サーバーからロードする必要のある請求書を印刷する必要がありました。請求書を(Webページとして)iFrameに読み込んでから印刷しました。もちろん、ページが完全に読み込まれるまで待機してから印刷する必要があったため、JSを一時停止する必要がありました。これは、iLoadの請求ページで、onLoadイベントを使用して親ページの非表示フォームフィールドを変更することで実現しました。また、請求書を印刷するための親ページのコードは次のようになりました(明確にするために無関係な部分は切り取られています)。

var isReady = eval('document.batchForm.ready');
isReady.value=0;

frames['rpc_frame'].location.href=url;

while (isReady.value==0) {
  java.lang.Thread.sleep(250);
} // endwhile

window.frames['rpc_frame'].focus();
window.frames['rpc_frame'].print();

したがって、ユーザーがボタンを押すと、スクリプトは請求書ページをロードしてから待機し、四半期ごとに請求書ページのロードが完了したかどうかを確認してから、ユーザーに印刷ダイアログをポップアップしてプリンターに送信します。QED。


12
著者が達成したかった単純なことを考えると、非常に巨大な解決策のようです。
xaralis 2013年

2
これは非推奨のJavaアプレットに依存します。
Vahid Amiri

6

多くの回答は質問に(直接)回答しません。また、これも回答しません...

これが私の2セント(または関数)です。

setTimeoutand ほど扱いにくい関数が必要な場合setIntervalは、引数の順序を逆にするだけの関数にそれらをラップして、適切な名前を付けることができます。

function after(ms, fn){ setTimeout(fn, ms); }
function every(ms, fn){ setInterval(fn, ms); }

CoffeeScriptバージョン:

after = (ms, fn)-> setTimeout fn, ms
every = (ms, fn)-> setInterval fn, ms

その後、無名関数でうまく使用できます。

after(1000, function(){
    console.log("it's been a second");
    after(1000, function(){
        console.log("it's been another second");
    });
});

これで、「Nミリ秒後...」(または「Nミリ秒ごと...」)と簡単に読み取れます。


5

ループによって実行されている一連の呼び出しの間隔を空けたいという特定のケースでは、プロトタイプで以下のコードのようなものを使用できます。プロトタイプがなければ、遅延関数をsetTimeoutに置き換えることができます。

function itemHandler(item)
{
    alert(item);
}

var itemSet = ['a','b','c'];

// Each call to itemHandler will execute
// 1 second apart
for(var i=0; i<itemSet.length; i++)
{
    var secondsUntilExecution = i;
    itemHandler.delay(secondsUntilExecution, item)
}

5

node.jsを使用している場合は、ファイバーを見ることができます。ノードへのネイティブC拡張であり、一種のマルチスレッドシミュレーションです。

それはあなたがsleepファイバーで実行をブロックしている方法で本当のことをすることを可能にします、しかしそれはメインスレッドと他のファイバーで非ブロックです。

ここに彼ら自身のreadmeからの新鮮な例があります:

// sleep.js

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

–結果は次のとおりです。

$ node sleep.js
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.