JavaScriptでスリープ-アクション間の遅延


129

JavaScriptが別のアクションを実行する前にスリープする方法はありますか?

例:

 var a = 1+3;
 // Sleep 3 seconds before the next action here
 var b = a + 4;

回答:


140

を使用setTimeoutして、同様の効果を得ることができます。

var a = 1 + 3;
var b;
setTimeout(function() {
    b = a + 4;
}, (3 * 1000));

これは実際にはJavaScriptを「スリープ」させるものではなくsetTimeout、特定の期間(ミリ秒で指定)後に渡された関数を実行するだけです。JavaScriptのスリープ関数を作成することは可能ですがsetTimeout、スリープ期間中にすべてを凍結しないため、可能であれば使用するのが最善です。


9
setInterval()もご覧ください。これはsetTimeout()に似ていますが、関数は(停止するまで)複数回呼び出されます。これは、スリープ中に何かを実行したい場合(進行状況の更新、内部状態の保持など)に役立ちます。
Anders Sandvig、

5
これは質問の答えにはなりません。質問はこれがそうではない「睡眠」同等物を求めます。
felwithe

この答えは質問が尋ねたものと一致しませんが、ループとDate.now()を比較するよりも便利です。ブロックされたループを使用して何をすべきか誰もがスリープしません。
Li Chunlin 2017

2
もちろん、閉塞ループがある場合を除き、正確に誰かが何を望んで。
Wonko the Sane

55

あなたが本当にsleep()何かをテストするためだけに必要な場合。ただし、デバッグ中にほとんどの場合ブラウザがクラッシュすることに注意してください。おそらくそれが必要な理由です。本番モードでは、この関数をコメントアウトします。

function pauseBrowser(millis) {
    var date = Date.now();
    var curDate = null;
    do {
        curDate = Date.now();
    } while (curDate-date < millis);
}

new Date()メモリ、処理能力、バッテリー、そして場合によってはデバイスの寿命を無駄にしたくない場合を除いて、ループでは使用しないでください。


8
この回答は、より多くの投票に値します。この質問の主な理由は、この回答の原因です。
jagc 2016年

「再帰が多すぎる」という警告はどうですか?
沖エリーリナルディ2017

1
@OkiErieRinaldi再帰はありません。ループのみです。
ロドリゴ

7
@ 3.1415926535897932384626433833さて、誰かが「スリープ」機能を要求しました。それがここにあります。一度使ったのですが、どのようなデバッグをしたのか正確に覚えられません。再び必要になった場合は、どこにあるかを正確に把握しています。別の機能が必要な場合は、それを選択してください。選べるのはいいですね。
ロドリゴ

2
「忙しい」
Zeek2 2017

13

ECMAScript 6バージョン、 "コードブロッキング"にyieldを含むジェネレーターを使用:

元の質問は7年前に投稿されたため、正確なコードでわざわざ答えることはしませんでした。これは、少なくとも2つのスリープが必要な場合や、非同期実行のシーケンスを計画している場合など、より複雑な問題に役立ちます。必要に応じて自由に変更してください。

let sleeptime = 100
function* clock()
{
    let i = 0
    while( i <= 10000 )
    {
        i++
        console.log(i); // actually, just do stuff you wanna do.
        setTimeout(
            ()=>
            {
                clk.next()
            }
            , sleeptime
        )
        yield
    }
}

let clk = clock()
clk.next()

関数*

()=>矢印関数

Promisesを介してイベントをチェーンすることもできます:

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


sleep(1000).then(function()
{
    console.log('1')
    sleep(1000).then(function()
    {
        console.log('2')
    })
})

またははるかにシンプルで派手な方法は

function sleep(ms, f)
{
    return(
        setTimeout(f, ms)
    )
}


sleep(500, function()
{
    console.log('1')
    sleep(500, function()
    {
        console.log('2')
    })
})
console.log('Event chain launched')

何らかの条件が発生するのを待っているだけなら、このように待つことができます

function waitTill(condition, thenDo)
{
    if (eval(condition))
    {
        thenDo()
        return
    }

    setTimeout(
        ()    =>
        {
            waitTill(condition, thenDo)
        }
        ,
        1
    )
}

x=0

waitTill(
    'x>2 || x==1'
    ,
    ()    =>
    {
        console.log("Conditions met!")
    }
)

// Simulating the change
setTimeout(
    () =>
    {
        x = 1
    }
    ,
    1000
)


11

2018年の更新

最新のSafari、Firefox、Node.jsもasync / await / promisesをサポートしています。

async / await / Promisesの使用:

(2017年1月現在、Chromeではサポートされていますが、Safari、Internet Explorer、Firefox、Node.jsではサポートされていません)

'use strict';

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

let myAsyncFunc = async function() {
  console.log('Sleeping');
  await sleep(3000);
  console.log('Done');
}

myAsyncFunc();

2017年アップデート

JavaScriptは、この質問が出されてから進化し、現在はジェネレーター関数があり、新しいasync / await / Promiseがロールアウトされています。以下に2つのソリューションがあります。1つはすべての最新のブラウザーで動作するジェネレーター機能を備えたソリューションで、もう1つはまだサポートされていない新しい非同期/待機を使用するソリューションです。

ジェネレータ関数を使用する:

'use strict';

let myAsync = (g) => (...args) => {
    let f, res = () => f.next(),
        sleep = (ms) => setTimeout(res, ms);
    f = g.apply({sleep}, args); f.next();
};

let myAsyncFunc = myAsync(function*() {
    let {sleep} = this;
    console.log("Sleeping");
    yield sleep(3000);
    console.log("Done");
});

myAsyncFunc();

これらのソリューションはどちらも本質的に非同期であることに注意してください。つまり、myAsyncFuncは(どちらの場合も)スリープ中に戻ります。

この質問は、sleep()のJavaScriptバージョンとは何ですか?リクエスタは、アクション間の遅延ではなく、実際のスリープ(プロセスでの他のコード実行なし)を求めています。


1
これまでのベストアンサー!! 私はそれを見つけるためにどこでも検索する30分を費やしました。大きなthx !!!
538ROMEO 2018

1
解決策を探しているときに私はこの答えを逃し、自転車を再発明しました:Dそれが私に何時間も節約する前にそれを見るとしたら!! 賛成です!
sserzant

let co = gen => (...args) => { let iter = gen(...args); let resume = () => new Promise((resolve, reject) => { let result = iter.next(); if (result.done) resolve(result.value); else Promise.resolve(result.value).then(resume).then(resolve, reject); }); return resume(); };2番目のコードブロックからlet asyncAdd = co(function* (a, b) { console.log('Sleeping'); yield sleep(3000); console.log('Done'); return a + b; }); asyncAdd(3, 4).then(console.log);の定義を使用して実行できsleep()ます。
Patrick Roberts

3

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ミリ秒ごと...」)と簡単に読み取れます。


2

これを行う別の方法は、PromiseとsetTimeoutを使用することです(関数内にいて、asyncキーワードで非同期として設定する必要があることに注意してください)。

async yourAsynchronousFunction () {

    var a = 1+3;

    await new Promise( (resolve) => {
        setTimeout( () => { resolve(); }, 3000);
    }

    var b = a + 4;

}

2

これは、同期のスリープ/一時停止のように「感じる」非常に簡単な方法ですが、正当なjs非同期コードです。

// Create a simple pause function
const pause = (timeoutMsec) => new Promise(resolve => setTimeout(resolve,timeoutMsec))

async function main () {
    console.log('starting');
    // Call with await to pause.  Note that the main function is declared asyc
    await pause(3*1000)
    console.log('done');
}


1

プレーンなjavascriptを使用できます。これにより、5秒後に関数/メソッドが呼び出されます。

setTimeout(()=> { your_function(); }, 5000);

0

この問題を解決するにはいくつかの方法があります。setTimeout関数を使用する場合は、最初にそれを知ってみましょう。 この関数は:三つのパラメータがあるfunctioncodedelay(ミリ秒単位)とparameters。以来、関数またはコードパラメータが必要であり、その他は任意です。遅延を入力しないと、ゼロに設定されます。

詳細についてはsetTimeout() 、このリンクにアクセスしてください

簡略版:

var a = 1 + 3;
var b;
console.log('a = ' + a);
setTimeout(function(){ 
    b = a + 4; 
    console.log('b = ' + b);
}, 1000);

出力:
a = 4
24->アクティブなタイムアウトのリストの番号識別子
b = 8


パラメータパスを使用:

var a = 1 + 3;
var b;
console.log('a = ' + a);
setTimeout(myFunction, 1000, a);

function myFunction(a)
{
    var b = a + 4;
    console.log('b = ' + b);
}

出力:
a = 4
25->アクティブなタイムアウトのリストの番号識別子
b = 8



ブラウザサポート:

Chrome Firefox Edge Safari Opera
1.0 1.0 4.0 1.0 4.0

0

これは、ジェネレーター関数(ES6)を使用してJavaScriptで「スリープ」または「DoEvents」する方法を示す私のモデルです。コメント付きコード:

<html>
<head>
<script>
  "use strict"; // always
  // Based on post by www-0av-Com /programming/3143928
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
  var divelt, time0, globaln = 0; // global variables
  var MainGenObj = Main(); // generator object = generator function()
window.onload = function() {
  divelt = document.getElementsByTagName("body")[0]; // for addline()
  addline("typeof Main: " + typeof Main);
  addline("typeof MainDriver: " + typeof MainDriver);
  addline("typeof MainGenObj: " + typeof MainGenObj);
  time0 = new Date().valueOf(); // starting time ms
  MainDriver(); // do all parts of Main()
}
function* Main() { // this is "Main" -- generator function -- code goes here
  // could be loops, or inline, like this:

  addline("Part A, time: " + time() + ", " + ++globaln); // part A
  yield 2000;                    // yield for 2000 ms (like sleep)

  addline("Part B, time: " + time() + ", " +  ++globaln); // part B
  yield 3000;                    // yield for 3000 ms (or like DoEvents)

  addline("Part Z, time: " + time() + ", " +  ++globaln); // part Z (last part)
  addline("End, time: " + time());
}
function MainDriver() { // this does all parts, with delays
  var obj = MainGenObj.next(); // executes the next (or first) part of Main()
  if (obj.done == false) { // if "yield"ed, this will be false
    setTimeout(MainDriver, obj.value); // repeat after delay
  }
}
function time() { // seconds from time0 to 3 decimal places
  var ret = ((new Date().valueOf() - time0)/1000).toString();
  if (ret.indexOf(".") == -1) ret += ".000";
  while (ret.indexOf(".") >= ret.length-3) ret += "0";
  return ret;
}
function addline(what) { // output
  divelt.innerHTML += "<br />\n" + what;
}
</script>
</head>
<body>
<button onclick="alert('I\'m alive!');"> Hit me to see if I'm alive </button>
</body>
</html>

0

この機能を試してください:

const delay = (ms, cb) => setTimeout(cb, ms)

使い方は次のとおりです。

console.log("Waiting for 5 seconds.")
delay(5000, function() {
  console.log("Finished waiting for 5 seconds.")
})

または約束のスタイルに行く:

const delay = ms => new Promise(resolve => {
    setTimeout(resolve, ms)
})

こちらがデモです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.