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


これまでにあなたのブラウザーのdevtoolsを前に、睡眠を含むいくつかのコードを実装しようとしたが、あなたの失望にはJavaScriptのネイティブスリープ機能が発見されたいじめ?それとも、JSのウェブサイトからのそれを実装しようとした?私は以前にそこにいたので、私がこれのために見つけた回避策を記述させてください、そして、あなたのコードがネットワーク要求をするのを必要とするならば、彼らはすべて不適当です.

睡眠の誤謬


ecmascriptはスリープ機能を定義しません.その結果として、それが動作する1つをしようとする盛り合わせハックの長いリストがあります.次の段落で見るように、すべての欠点があります.
JavaScriptで眠るための公式スタックオーバーフロー質問です.2408 upvotes(そして、この記事を作成してから12以上)を持って、11年以上の期間にわたって2.80万回を見られました.

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


ジュン4 ' 09
コメント: 7
回答83件
2738

エンジニアをするより良い方法はありますかsleep 以下のJavaScriptでpausecomp 関数taken from here )?
function pausecomp(millis)
{
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < millis);
}
これは.
Open Full Question
今、睡眠は非常に重要です.あなたがAPIからデータを取り込んでいると仮定してください、そして、データがいくつかの「次のポインタ」の上に広げられて、いくつかの要求をするのを必要とします.あなたが一度にすべての要求を発射した場合、または単に機能不全sleep , あなたがブロックを取得するリスク429 Too many requests ステータスコード.InstagramのGraphSQL終点はこれを行うAPIの例です.リクエストの間のスリープ機能の異なる実装を通して私のコードパスを作ったことがいくつかありました.
ブラウザーの使用には、ビジー状態の待機を使用するソリューションは不適切です.ブラウザが実行されるとき、ブラウザはスクリプトがブラウザを遅くしているという警告を表示し、ユーザーにオプションを与えるようにします.これはあなたのJavaScriptコードを停止します.それで、我々は他のオプションを調査しなければなりません.
一番上の解決策は以下の断片を使います:
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

// It's called using `await sleep(ms)`.

問題


これは正常に機能しますが、async関数が通常の関数で呼び出されない場合に限ります.この関数はwaitを使用します.これは、関数が眠っている間、非同期呼び出しの実行を再開するという不快な結果をもたらします.もしあなたのコードがシリアルに実行され、呼び出し元が呼び出した関数が終了するまで実行を再開しない場合を想定しますasync その仮定を破る.
JavaScriptではasync 親関数と独立して動く関数.親関数が、await キーワード、親関数もasyncとラベルをつけなければなりませんasync 関数.あなたのコードを書くことに関して何も間違っていませんがawait async関数が他の型を返す場合でもresolve() ). だから今、あなたは残りの機能体をthen() 呼び出し、そして、あなたがものを返すときはいつでも、それらは他の糸で包まれるので、それからすぐに.then() もう一度返り値を使いたいなら、最後ならthen() 関数では、その約束内の返り値がasync 呼び出し元.
このように考えてみましょう.
async function someFunc() { /* ... */ }

async function callee() {
  p = await someFunc()
  // `p` is a Promise
  p.then(ret => {
    // `ret` is whatever `someFunc` was supposed to return
  })
}
そして、以下のように、この問題に良い解決策はありません.スタックオーバーフロー質問に対する他の答えは、過度に複雑です.

再帰、ループしないでください?


私は、ループオーバーフローでは、スタックオーバーフローの質問では、トップソリューションを使用して、単に実行時に不快な驚きを残して使用してハードの方法を発見したsleep ループカウンタの各値に対して同時に実行されます(whileステートメントを使用した場合は無限大).これは最終的にブラウザをクラッシュさせる.
再帰は、同じパラメータでその内部の非同期関数を呼び出し、同じステートメントでその値をすぐに返す回避策です.これにより、再帰的な状態を保つように条件を実装することもできます.これがどのように動作するかです.
async function sleep(ms) { /* exact same `sleep` function as above */ }

async function foo(bar) {
  someAsyncFunc().then(retSomeAsyncFunc => {
    if (/* some condition involving `retSomeAsyncFunc` matches */) {
      // This returns a promise with the return value inside
      // to whoever called `foo()` initially
      return foo(bar)
    }
    // Additional processing...
    return someValue // Optional, can return nothing at all
  })
}
このコンテキストで再帰を使用する場合の大きな問題は、あなたが再帰(“ループ”)を過ぎると、呼び出しスタックのサイズ制限を打つかもしれません.各ブラウザには別の呼び出しスタックの制限があるので、再帰しながら注意してください.
入れ子になったループを必要とするとすぐに、このアプローチも非常に厄介になります.外側ループを内部ループの再帰を呼び出す再帰にどのようにすればよいのでしょうか.
前の段落を理解していなくても、2つのループが1つの再帰関数を共有できないことがわかりやすいです.問題は?

グローバル変数を設定します。


もう一つの回避策はsetInterval() あなたがスリープ状態にしたい時間と、コールバック関数のループ本体を使用します.このアプローチには2つの欠点があります.
  • コールバックは引数を取ることができないので、関数引数はグローバル変数の中に置かれなければなりません.
  • このアプローチは、より内側のループを追加するとすぐに崩壊します.
  • アトミック待つ?


    私は、最も運が適切に働くためにこれを得ていました.この関数は、async関数の外部でも動作します.nodejsではなく、FirefoxやChromeで動作するようです.ブラウザの残りは実装しないAtomics.wait . それで、この解決はあなたのウェブページがフェッチするdevtoolsスクリプトまたはクライアント側のJSのために働きません.
    function sleep(n) {
      Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, n);
    }
    
    *メインスレッドで走っているからです.アトミックを呼び出すことができます特別なケースの全体的な説明です.WebGLのレンダリングのような特定のワーカースレッドで待機しますが、ここではカバーしません.

    NODEJSを使用しますか?


    本当の睡眠機能は、サードパーティのNPMのモジュールと呼ばれる利用可能ですsleep , そして、あなたはそれを2つのコードの経路を分割しないことをカウントすることができます(そして3、4、あなたがそれを呼び出すたびに、潜在的に多くのネットワーク要求を意味する).タイムアウトが経過するまで待ちます.約束をしたり、async/を待つ必要はありません.
    これは私の意見では、究極の睡眠機能ですそれは、その機能のためのネイティブのサポートを持っている言語で書かれています.残念ながら、このような等価なブラウザはありません.これは特にNODEJSソリューションです.
    このモジュールを使用する不利な点は、眠っている間、イベントループ全体が止まるということです.これはあなたが望むものであるかもしれません、しかし、あなたが両方の世界の少しを捜していたならば、すなわち、一つの糸のために眠っていて、それはここにありません.
    また、このモジュールはC +に書かれているので、インストールするためにコンパイルする必要があります.Visual Studioのビルドツールとツールキットをノードと一緒にインストールせずにこれを行うことはできません.

    ジャバスクリプト


    JavaScriptは伝統的な言語から完全に異なる実行フローを持っています.つのパラダイム、非同期/約束、または他のループを完全に使用するコードを書かなければなりません.この記事がちょうど示したように、中間コースがありません.そして、約束を返す組み込み関数の数は、ブロック操作をより多くの実行不可能にするループを使用します.
    あなたがネットワーク要求をするつもりであるならば、あなたのJavaScriptアプリを伝統的な方法で書きません.これらはすべて非同期であり、すべての親関数を非同期にし、関数本体をthen . あなたは、睡眠の異なる実装を使用することができますが、ループを必要としない場合に限ります.ループステートメントを使用しないようにループを展開します.

    そして、我々はしました


    私はこの問題を持っている可能性がありますフィードバックだけでなく、何かを持っている場合、この問題を処理するための記事の修正とより良い提案を開いています.
    イメージバイPexels からPixabay