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

2541
fmsf 2009-06-05 04:41.

sleep次のpausecomp関数(ここから取得)よりもJavaScriptでaを設計するためのより良い方法はありますか?

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

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

30 answers

2991
Dan Dascalescu 2016-10-07 23:44.

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機能は、この「スリープ」関数の作成に役立ちました。

  • Promises、ES2015(別名ES6)のネイティブ機能。また、スリープ関数の定義では矢印関数を使用します。
  • このasync/await機能により、コードは約束が解決する(解決または拒否する)のを明示的に待機できます。

互換性

  • 約束はサポートされているノードv0.12 +にし、広くブラウザでサポートされているIEを除いて、
  • async/ awaitV8に搭載され、Chrome 55(2016年12月にリリース) 以降、デフォルトで有効になっています
    • 2016年10月にノード7に着陸しました
    • 2016年11月にFirefoxNightlyにも上陸しました

なんらかの奇妙な理由で、7より古いノード(寿命に達した)を使用している場合、または古いブラウザーをターゲットにしている場合でも、async/awaitはBabel(JavaScript +新機能をプレーンな古いJavaScriptに変換するツール)を介して使用できます。 、transform-async-to-generatorプラグイン付き。

852
Ben Flynn 2011-05-14 03:21.

(2016年の更新された回答を参照してください)

アクションを実行し、待ってから、別のアクションを実行することは完全に合理的だと思います。マルチスレッド言語での記述に慣れている場合は、スレッドがウェイクアップするまで、設定された時間実行を実行することを考えているでしょう。

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

したがって、他の人が提案したことにほとんど固執しています。コードを複数の関数に分割する必要があります。

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

684
gsamaras 2009-06-05 04:46.

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

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

編集

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

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

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

// Usage!
sleep(500).then(() => {
    // Do something after the sleep!
});
315
StephaneAG 2013-07-30 14:31.

デバッグ/開発の場合のみ、誰かに役立つ場合はこれを投稿します

興味深いことに、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 !"); }
180
DevinB 2009-06-05 04:55.

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

ただし、setTimeoutは実行を保留せず、タイムアウトが期限切れになった後ではなく、タイムアウトがSETされた直後に関数の次の行を実行するため、スリープが実行するのと同じタスクを実行しません。

それを行う方法は、機能をパーツの前後に分解することです。

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に制御を戻し、キューに入れられた他のすべてを実行します。

さらに編集

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

136
Philip Rego 2009-06-05 04:44.

$ 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を使用して、毎秒テキストを表示および非表示にする方法を示しています。

112
mjaggard 2011-11-05 04:16.

これは少し古い質問ですが、(私のように)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.
   */
}
71
Alan Plum 2009-06-11 08:50.

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');
48
a_w 2011-06-15 10:50.

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

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

...そして、クライアントサイドソリューションとの別のリンクは次のとおりです。 http://www.devcheater.com/

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

30
Ian Maddox 2012-11-03 16:02.

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

// 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) {}
}
29
pguardiario 2014-11-04 13:22.

同期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);

25
Ahmed Mohammedali 2019-06-27 01:27.

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

呼び出し元の関数が非同期であることを確認してください

検証済みで正常に動作している

22
melMass 2016-11-13 09:56.

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

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

その後:

sleep(2); // Sleeps for 2 seconds

P5jsでスクリプトを作成している間、偽の読み込み時間を作成するために常にそれを使用しています

21
Pablo Fernandez 2009-06-05 04:47.

最初:

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

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

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

setTimeout(alertWorld,1000)

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

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

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

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

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

複数のスリープが必要な場合、これは急いで醜くなる可能性があり、実際にデザインを再考する必要があるかもしれないことに注意してください。

13
fuweichin 2019-06-02 01:01.

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){}
%>
11
Homer6 2013-05-18 12:53.

ブラウザの場合、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

11
Gabriel Ratener 2014-06-25 20:05.

ここでの回答のほとんどは、誤った方向に進んでいるか、少なくとも時代遅れです。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
Elo 2015-07-10 03:59.

他の非同期タスクとのコードの一貫性のために、setTimeOutをPromiseにカプセル化します:Fiddleのデモ

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

そのように使用されます:

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

Promisesを使用していた場合は、構文を覚えるのは簡単です。

8
user207408 2009-11-10 18:22.

私はjavascriptのsleep / waitでかなりの数のウェブページを検索/グーグルで検索しました...そしてjavascriptを「RUN、DELAY、RUN」にしたい場合は答えがありません...ほとんどの人が得たのは「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>
7
Shemeer M Ali 2013-11-10 08:37.
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
7
1j01 2015-01-04 18:41.

多くの答えは(直接)質問に答えません、そしてこれも...

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

setTimeoutおよびよりも不格好な関数が必要な場合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ミリ秒ごと...」)と簡単に読み取ることができます。

7
k06a 2019-11-20 03:34.

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

await new Promise(resolve => setTimeout(resolve, 5000));
6
Andrew Dunkman 2009-06-05 04:46.

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

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

6
acuth 2010-10-19 09:45.

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

6
naazgull 2011-06-22 07:41.

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

6
Rachael 2013-01-14 15:32.

これは、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にロードしてから、iFrameを印刷することでそれを行いました。もちろん、印刷する前にページが完全に読み込まれるまで待たなければならなかったので、JSは一時停止しなければなりませんでした。これは、(iFrame内の)請求書ページで、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();

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

6
tomekwi 2015-02-07 00:55.

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)
5
beauburrier 2010-05-28 09:45.

ループによって実行されている一連の呼び出しの間隔を空けたいという特定のケースでは、プロトタイプで以下のコードのようなものを使用できます。プロトタイプがない場合は、遅延関数を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
Ole Middelboe 2015-10-10 14:43.

2009年の古い質問です。2015年には、ECMAscript 2015(別名ES6)で定義されたジェネレーターを使用して新しいソリューションが可能になりました。6月に承認されましたが、以前はFirefoxとChromeに実装されていました。これで、ブラウザーをフリーズすることなく、スリープ関数をビジー、ブロッキング、ネストされたループおよびサブ関数内に作成できます。純粋なJavaScriptのみが必要であり、ライブラリやフレームワークは必要ありません。

以下のプログラムは、その方法sleep()runSleepyTask()作成方法を示しています。sleep()機能があるだけでyield声明。非常に単純なのでyield、を呼び出す代わりにステートメントを直接記述する方が実際には簡単ですsleep()が、スリープワードはありません:-)歩留まりはnext()内部のメソッドに時間値を返し、wakeup()待機します。実際の「睡眠」はwakeup()古き良きものを使って行われsetTimeout()ます。コールバック時に、next()メソッドはyieldステートメントをトリガーして続行します。yieldの「魔法」は、すべてのローカル変数とその周囲の呼び出しスタック全体がそのままであるということです。

sleep()またはyieldを使用する関数は、ジェネレーターとして定義する必要があります。キーワードにアスタリスクを追加することで簡単に行えfunction*ます。ジェネレーターを実行するのは少し難しいです。キーワードを指定して呼び出すと、newジェネレーターはnext()メソッドを持つオブジェクトを返しますが、ジェネレーターの本体は実行されません(キーワードnewはオプションであり、違いはありません)。このnext()メソッドは、に遭遇するまでジェネレーター本体の実行をトリガーしますyield。ラッパー関数はrunSleepyTask():ピンポンを起動next()するために待機しyield、そしてyield待機しますnext()

ジェネレーターを呼び出す別の方法は、キーワードyield*を使用することです。ここでは、単純な関数呼び出しのように機能しますが、に戻る機能も含まれていnext()ます。

これはすべて、例で示されていますdrawTree()。回転する3Dシーンに葉のある木を描画します。木は幹として描かれ、上部に3つの部分が異なる方向にあります。次にdrawTree()、短いスリープの後に再帰的に呼び出すことにより、各部分が別の小さいツリーとして描画されます。非常に小さな木が葉だけとして描かれています。

各葉には、で始まる個別のタスクで独自の生命がありますrunSleepyTask()。それは生まれ、成長し、座り、衰退し、落下し、そして死ぬgrowLeaf()。速度はで制御されsleep()ます。これは、マルチタスクを簡単に実行できることを示しています。

function* sleep(milliseconds) {yield milliseconds};

function runSleepyTask(task) {
    (function wakeup() {
        var result = task.next();
        if (!result.done) setTimeout(wakeup, result.value);
    })()
}
//////////////// written by Ole Middelboe  /////////////////////////////

pen3D =setup3D();
var taskObject = new drawTree(pen3D.center, 5);
runSleepyTask(taskObject);

function* drawTree(root3D, size) {
    if (size < 2) runSleepyTask(new growLeaf(root3D))
    else {
        pen3D.drawTrunk(root3D, size);
        for (var p of [1, 3, 5]) {
            var part3D = new pen3D.Thing;
            root3D.add(part3D);
            part3D.move(size).turn(p).tilt(1-p/20);
            yield* sleep(50);
            yield* drawTree(part3D, (0.7+p/40)*size);
        }
    }
}

function* growLeaf(stem3D) {
    var leaf3D = pen3D.drawLeaf(stem3D);
    for (var s=0;s++<15;) {yield* sleep(100); leaf3D.scale.multiplyScalar(1.1)}
    yield* sleep( 1000 + 9000*Math.random() );
    for (var c=0;c++<30;) {yield* sleep(200); leaf3D.skin.color.setRGB(c/30, 1-c/40, 0)}
    for (var m=0;m++<90;) {yield* sleep( 50); leaf3D.turn(0.4).tilt(0.3).move(2)}
    leaf3D.visible = false;
}
///////////////////////////////////////////////////////////////////////

function setup3D() {
    var scene, camera, renderer, diretionalLight, pen3D;

    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(75, 
        window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.set(0, 15, 20);
    renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    
    directionalLight = new THREE.DirectionalLight(0xffffaa, 0.7);
    directionalLight.position.set(-1, 2, 1);
    scene.add(directionalLight);
    scene.add(new THREE.AmbientLight(0x9999ff));
      
    (function render() {
        requestAnimationFrame(render);
        // renderer.setSize( window.innerWidth, window.innerHeight );
        scene.rotateY(10/60/60);
        renderer.render(scene, camera);
    })();
    
    window.addEventListener(
        'resize',
        function(){
            renderer.setSize( window.innerWidth, window.innerHeight );
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
       }, 
       false
    );
    
    pen3D = {
        drawTrunk: function(root, size) {
            // root.skin = skin(0.5, 0.3, 0.2);
            root.add(new THREE.Mesh(new THREE.CylinderGeometry(size/12, size/10, size, 16), 
                root.skin).translateY(size/2));
            root.add(new THREE.Mesh(new THREE.SphereGeometry(size/12, 16), 
                root.skin).translateY(size));
            return root;
        },
        
        drawLeaf: function(stem) {
            stem.skin.color.setRGB(0, 1, 0);
            stem.add(new THREE.Mesh(new THREE.CylinderGeometry(0, 0.02, 0.6), 
                stem.skin) .rotateX(0.3).translateY(0.3));
            stem.add(new THREE.Mesh(new THREE.CircleGeometry(0.2), 
                stem.skin) .rotateX(0.3).translateY(0.4));
            return stem;
        },
        
        Thing: function() {
            THREE.Object3D.call(this);
            this.skin = new THREE.MeshLambertMaterial({
                color: new THREE.Color(0.5, 0.3, 0.2),
                vertexColors: THREE.FaceColors,
                side: THREE.DoubleSide
            })
        }
    };

    pen3D.Thing.prototype = Object.create(THREE.Object3D.prototype);
    pen3D.Thing.prototype.tilt = pen3D.Thing.prototype.rotateX;
    pen3D.Thing.prototype.turn = pen3D.Thing.prototype.rotateY;
    pen3D.Thing.prototype.move = pen3D.Thing.prototype.translateY;
    
    pen3D.center = new pen3D.Thing;
    scene.add(pen3D.center);
    
    return pen3D;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>

3Dのものはsetup3D()内に隠されており、console.log()よりも退屈さを少なくするためにのみ含まれています。ちなみに、天使はラジアンで測定されます。

FirefoxとChromeで動作することがテストされています。Internet ExploreおよびiOS(iPad)には実装されていません。自分で実行してみてください。

私が見つけた答えの別のパスの後、そのガブリエル・レイターは1年前に同様の答えをしました: https://stackoverflow.com/a/24401317/5032384

Related questions

MORE COOL STUFF

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは、夫に会ったとき、典型的な交際のアドバイスに逆らいました。

マイケルシーンが非営利の俳優である理由

マイケルシーンが非営利の俳優である理由

マイケルシーンは非営利の俳優ですが、それは正確にはどういう意味ですか?

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

特徴的なスターのコリン・エッグレスフィールドは、RomaDrama Liveでのスリル満点のファンとの出会いについて料理しました!加えて、大会での彼のINSPIREプログラム。

「たどりつけば」をオンラインでストリーミングできない理由

「たどりつけば」をオンラインでストリーミングできない理由

ノーザンエクスポージャーが90年代の最も人気のある番組の1つになった理由を確認するには、Blu-rayまたはDVDプレーヤーをほこりで払う必要があります。

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖は、世界で2番目に大きいボイリング湖です。そこにたどり着くまでのトレッキングは大変で長いですが、努力する価値は十分にあります。

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

サロンからのヘアトリミングや個人的な寄付は、油流出を吸収して環境を保護するのに役立つマットとして再利用できます。

ホワイトハウスの最も記憶に残る結婚式を見てください

ホワイトハウスの最も記憶に残る結婚式を見てください

過去200年以上の間にホワイトハウスで結婚したのはほんの数人です。彼らは誰でしたか、そしてそこで結婚式を獲得するために何が必要ですか?

驚くほど素晴らしいDropMixミュージックミキシングカードゲームは30ドルで驚くべき取引です

驚くほど素晴らしいDropMixミュージックミキシングカードゲームは30ドルで驚くべき取引です

DropMixはNFC対応のカードゲームで、基本的にはリミックスアーティストになります。現在、Amazonでは$ 30まで下がっており、これまでで最高の価格に匹敵します。ロックバンドで有名なHarmonixによって開発されたDropMixは、おそらく少し野心的すぎるように思われます。結局のところ、ほとんどの人は素晴らしいリズムを持っていませんが、ゲームは驚くほどうまく実行されます。

メアリーJ.ブライジがついにハリウッドウォークオブフェイムスターを獲得

メアリーJ.ブライジがついにハリウッドウォークオブフェイムスターを獲得

写真:APメアリーJ.ブライジは、間もなくハリウッドウォークオブフェイムのスターを獲得します。これは、メアリーJよりもハリウッドウォークオブフェイムのほうが正直なところ恩恵です。

MeltdownとSpectreの脆弱性についてこれまでに知っていることはすべて、簡単な方法で説明されています

MeltdownとSpectreの脆弱性についてこれまでに知っていることはすべて、簡単な方法で説明されています

画像:グラズ工科大学/ NataschaEiblがデザインしたロゴ。MeltdownとSpectreは、攻撃者がシステムメモリに保存されているあらゆる種類の情報にアクセスできるようにする2つの脆弱性に付けられた名前です。

彼のニューヨークの家から追い出されようとしている97歳の第二次世界大戦の獣医。メリーエフィングクリスマス

彼のニューヨークの家から追い出されようとしている97歳の第二次世界大戦の獣医。メリーエフィングクリスマス

日本人に襲われたときに真珠湾にいた97歳の第二次世界大戦のベテランが、ニューヨークのブルックリンから追い出されています。

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya shared a sweet photo in honor of boyfriend Tom Holland's 26th birthday Wednesday

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

シーレン「Ms.JuicyBaby」ピアソンは、先月脳卒中で入院した後、「もう一度たくさんのことをする方法を学ばなければならない」ため、言語療法を受けていることを明らかにしました。

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

オスカー受賞者の世紀半ばの家には、3つのベッドルーム、2つのバス、オーシャンフロントの景色があります。

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、生後4か月の娘、モナコに母乳育児をしていると語った。

投資ノート:Bioscout AU$300万シード

投資ノート:Bioscout AU$300万シード

Bioscoutは、農家を運転席に置くという使命を負っています。Artesian(GrainInnovate)やUniseedと並んで、最新のシードラウンドでチームを支援できることをうれしく思います。問題真菌症による重大な作物の損失は、農民にとって試練であることが証明されています。

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

遠隔医療は、パンデミック後の時代では新しいものではなく、時代遅れの分野でもありません。しかし、業界を詳しく見ると、需要と供給の強力な持続可能性と、米国で絶え間ない革命となる強力な潜在的成長曲線を示しています。

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

2021年は、世界的なベンチャーキャピタル(VC)の資金調達にとって記録的な年でした。DealStreetAsiaによると、東南アジアも例外ではなく、この地域では年間で記録的な25の新しいユニコーンが採掘されました。

ムーアの法則を超えて

ムーアの法則を超えて

計算に対する私たちの欲求とムーアの法則が提供できるものとの間には、指数関数的に増大するギャップがあります。私たちの文明は計算に基づいています—建築と想像力の現在の限界を超える技術を見つけなければなりません。

Language