問題タブ [job-queue]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票する
3 に答える
872 参照

javascript - promise、タスク、およびジョブ キューを使用した非同期 JS の理解

私はJSの非同期動作を調べていましたが、ほとんどの場合うまくいきました。コードを同期的に実行する方法、JS のシングル スレッド、および setTimeout 内のコールバックなどのコールバックが Web ブラウザ API によってタイミングを計られ、後でタスク キューに追加される方法を理解しています。

イベント ループはコール スタックを常にチェックし、それが空の場合 (すべての同期コードが実行された場合) にのみ、タスク キューにキューイングされた関数を取得します。それらをコール スタックにプッシュし、実行します。

これは非常に簡単で、次のコードの理由です。

を出力しますstart, end, timeout

promise について読み始めたとき、タイムアウト、間隔、イベントリスナーなどの通常の非同期コードよりも優先度が高く、代わりにジョブ キュー/マイクロタスク キューに配置されることがわかりました。イベント ループは、最初にそのキューに優先順位を付け、すべてのジョブを使い果たすまで実行してから、タスク キューに移動します。

これはまだ意味があり、次を実行することで確認できます。

これは を出力しますstart, end, promise, timeout。同期コードが実行され、thenコールバックがマイクロタスク キューからスタックにプッシュされて実行され、タスク キューから setTimeout コールバック タスクがプッシュされて実行されます。これまでのところすべて順調です。

公式ドキュメントで説明されているように、promise が即時かつ同期的に解決される上記の例に頭を悩ませることができます。new キーワードで promise を作成し、executor 関数を提供する場合も同じことが起こります。そのエグゼキューター関数は同期的に実行され、関数を解決します。したがって、 then が発生すると、解決された promise で非同期に実行できます。

上記のスニペットはstart, promise 1 log, end, promise 1、executor が同期的に実行されていることを証明する出力を出力します。

そして、これは約束と混同される場所です。次のコードがあるとしましょう:

これにより、 が発生しstart, promise 1 log, end, promise 1ます。エグゼキューター関数がすぐに実行される場合、その関数内の setTimeout が後で実行するためにタスク キューに置かれることを意味します。私の理解では、これは約束が現在も保留中であることを意味します。thenメソッドとその中のコールバックに到達します。これはジョブ キューに入れられます。残りの同期コードが実行され、空のコール スタックが作成されます。

私の理解では、約束のコールバックが優先されますが、まだ解決されていない約束でどのように実行できますか? promise は、その中の setTimeout が実行された後にのみ解決する必要がありますが、これはまだタスク キュー内にあります。追加の説明なしに、約束が解決された場合にのみ実行されると聞いたことがあります。私の出力から、それが真実であることがわかりますが、この場合にどのように機能するかわかりません。私が考えることができる唯一のことは、例外または類似のものと、マイクロタスクの前にタスクキュータスクが優先されることです。

これは長くなってしまったので、これを読んで答えてくれた人に感謝します。タスク キュー、ジョブ キュー、およびイベント ループをよりよく理解したいので、ためらわずに詳細な回答を投稿してください。前もって感謝します。

0 投票する
1 に答える
485 参照

python - 忙しい待機なしで、redis キュー内のジョブが完了するまでエレガントに待機しますか?

現在のシステムにredis キューを実装しようとしています。はjob別のモジュールに送信され、ジョブが完了して結果が返されるまで待機しjob.result、次に進みます。

ここで2つの問題に直面しています:

  1. ビジー状態でwhile job.result is None、非常に長い時間がかかっています。での私の処理worker_funcは約 2 ~ 3 秒で、別のサーバーで API を呼び出す必要がありますが、ビジー状態の待機while job.result is None自体にさらに 3 秒以上かかり、合計で 5 秒以上かかります。とwhile job.result is Noneの両方のログを追加したため、 の実行後に待機が行われることは確かです。worker_funcwhile job.result is None

上記でわかるように、ビジー状態の待機中のループは、処理worker_funcが完了した後に発生します。

2、ビジーループの代わりに、この同期待機を実装する他のエレガントな方法はありますか? ここでのビジー ループは、多くの CPU リソースを消費するため、最適な実装ではないと思います。

ありがとう!

-- 上記のコードを編集して、より明確なコンテキストを提供します

が呼び出された場所から値をnext_step_func(job.result)返す必要があります。job_queue.enqueueしたがって、より明確な構造は次のようになります。

job.resultそのため、問題は、で返されることができる必要があることですがendpoint()、ジョブ コールバックによって、ジョブが の別のコンテキストに移されon_successます。