web-dev-qa-db-ja.com

JavaScriptスリープ

はい、私は知っています-その質問には何千もの答えがあります。 setTimeoutメソッドについて教えてはいけません。-はい、それですべてが可能ですが、sleep()メソッドを使用するほど簡単ではありません。

例えば:

_function fibonacci(n) {
    console.log("Computing Fibonacci for " + n + "...");
    var result = 0;

    //wait 1 second before computing for lower n
    sleep(1000);
    result = (n <= 1) ? 1 : (fibonacci(n - 1) + fibonacci(n - 2));

    //wait 1 second before announcing the result
    sleep(1000);
    console.log("F(" + n + ") = " + result);

    return result;
}
_

setTimeoutを使用して同じ結果を取得する方法を知っている場合-教えてください;)再帰は2つ以下なので、fibanacciは非常に簡単な作業ですが、n回の再帰(fib(1)+など)はどうでしょうか。 fib(2)+ .. + fib(n))そして「+」ごとにスリープしますか?いや、睡眠はずっと楽になるでしょう。

しかし、それでも私はそれを実装する実際の例を得ることができません。 while (curr - start < time) { curr = (...) }は注意が必要ですが、機能しません(ブラウザーを停止してから、すべてのコンソールログを一度にスローするだけです)。

9
Diazath

私はあなたが何を求めているのか完全には理解していませんが、私はこの部分に答えるつもりです:

setTimeoutを使用して同じ結果を取得する方法を知っている場合-教えてください

基本的な違いは、sleep(他の多くの言語で使用されている)は同期的であるのに対し、setTimeout(およびAJAXなど)などの他の多くのJavaScriptの概念) )は非同期です。したがって、関数を書き直すには、これを考慮に入れる必要があります。主に、実際のreturnステートメントではなく、コールバックを使用して「戻り値」をフェッチする必要があるため、次のように使用されます。この:

fibonacci(7, function(result) {
  // use the result here..
});

だから、実装に関しては:

function fibonacci(n, callback) {
  console.log("Computing Fibonacci for " + n + "...");
  var result = 0;

  var announceAndReturn = function() {
    setTimeout(function() {
      // wait 1 second before announcing the result
      console.log("F(" + n + ") = " + result);
      callback(result); // "returns" the value
    }, 1000);
  };

  // wait 1 second before computing lower n
  setTimeout(function() {
    if (n <= 1) {
      result = 1;
      announceAndReturn();
    }
    else {
      var resultsLeft = 2;

      var handler = function(returned) {
        result += returned;
        resultsLeft--;
        if (resultLeft == 0)
          announceAndReturn();
      }

      fibonacci(n-1, handler);
      fibonacci(n-2, handler);
    }
  }, 1000);
}

また、no、これはsleepを使用するよりも簡単な解決策ではないことも指摘しておきます。どうして?このコードは非同期であり、ほとんどの人が慣れている同期コードよりも単純に複雑だからです。そのように考え始めるには練習が必要です。

良い面は?これにより、同期アルゴリズムよりも優れた非ブロッキングアルゴリズムを記述できます。 Node.js について聞いたことがない場合は、これをチェックして、この利点をさらに理解することができます。 (他の多くの言語には、非同期を処理するためのライブラリがありますIOですが、JavaScriptについて話している限り..)

20
Jakob

問題は、JavaScriptでsleep()を実装する方法を尋ねることです。

function sleep(ms) {
  var start = new Date().getTime(), expire = start + ms;
  while (new Date().getTime() < expire) { }
  return;
}

私はちょうどそのようにそれをテストしました:

console.log('hello');
sleep(5000);
console.log('world');

私のために働きます。

(メタコメントとして:この関数が特に必要なため、ここに着陸しました。値を待っている間にブロックするneedの場合、このようなニーズが発生します。JavaScriptでも。)

34
Murph

ブラウザ(またはその他のGUI環境)内のsleep()型関数の問題は、それがイベント駆動型環境であり、sleep()を実行できないことです。あなたがそれを説明している方法で。

setTimeout()メソッドは、イベントを作成し、そのイベントのトリガーを特定の時点に設定しているため、機能します。したがって、システムはイベントハンドラーの待機の制御を引き継ぐことができ、Javascript自体は他のことを自由に実行できます。

Webブラウザーでは、事実上すべてがこのように機能します。マウスクリック/ホバー/その他の機能はイベントトリガーです。 Ajaxリクエストは、サーバーからの応答を待って待機することはありません。応答を受信したときにトリガーするイベントを設定します。

時間ベースのアクションも、setTimeout()などの関数を使用してイベントトリガーで実行されます。

これがその方法です。実際、これは、ほとんどすべての適切に作成されたGUIアプリケーションで行われる方法です。これは、すべてのGUIインターフェイスが、マウスクリックなどのイベントに事実上即座に応答できる必要があるためです。

Javascript sleep()関数(特にここでの別の回答で実装されている方法!)は、基本的に、クロックを待機している間にCPUサイクルを焼き尽くす効果があります。 sleep()はアクティブなプロセスのままです。つまり、他のイベントがすぐに処理されない可能性があります。つまり、スリープ中はブラウザがマウスクリックなどに応答しなくなったように見えます。良くないことです。

setTimeout()がその方法です。それを行う方法は常にあります。結果のコードは、サンプルコードのようにきちんと線形ではない場合がありますが、イベント駆動型コードが線形になることはめったにありません。解決策は、プロセスを小さな機能に分割することです。後続の関数をsetTimeout()呼び出し内に埋め込むこともできます。これは、コードが少なくとも線形のように見えるようにするのに役立つ場合があります。

それがあなたのために物事を少し説明するのに役立つことを願っています。

3
Spudley

より良いアルゴリズム をループや再帰なしで使用し、setTimeout()/sleep()の必要性を回避してください。

function fibonacci(n) {
  return Math.round(Math.pow((Math.sqrt(5) + 1) / 2, Math.abs(n)) / Math.sqrt(5)) * (n < 0 && n % 2 ? -1 : 1);
}

使用例:

// Log the first 10 Fibonacci numbers (F0 to F9) to the console
for (var i = 0; i < 10; i++) {
  console.log(fibonacci(i));
}
2
Mathias Bynens

一体なぜあなたは何かを計算している間「眠りたい」のですか?いつでも眠ることはほぼどの言語でも常に悪い考えです。基本的に、その期間は何もしないようにスレッドに指示します。

それで、スレッドが1つしかない(「Webワーカー」を忘れる)javascriptのような言語では、すべての計算を一時停止することでどのようなメリットが得られますか?それは悪い考えです、それを忘れてください。

さて、あなたが書いた問題についてですが、これはあなたの実際の問題ではないと思います。このシーケンスの計算中に、なぜ1秒間一時停止したいのですか?シーケンスの最初の6つの数値を計算する場合でも、8秒ほどかかります。どうして?再帰呼び出しの間に1秒間一時停止する理由として考えられるものは何ですか?やめて。それを除く。

完了後1秒で最終結果を生成したい場合は、関数でsetTimeoutを使用すると、何らかの方法で回答が使用されます。

function fib(n) {
    ...
    result = fib();
    ...
    setTimeout(function() {
        console.log("Fib for " + n + " is " + result);
    },1000);
}

'sleep'を実装しようとしないでください。計算中に一時停止しないでください。

0
Josh Smeaton