jQueryの約束に頭を悩ませるのに苦労しています。jQueryの約束を調べるために次のスニペットを作成しました。このStackOverflowエントリによって通知されます。
let q = [
function () { setTimeout(function () { console.log("a - " + Date.now()); }, 5000); },
function () { setTimeout(function () { console.log("b - " + Date.now()); }, 2500); },
function () { setTimeout(function () { console.log("c - " + Date.now()); }, 0); }
];
function SerialCall(queue) {
var d = $.Deferred().resolve();
while (queue.length > 0) {
d = d.then(queue.shift()); // you don't need the `.done`
}
}
SerialCall(q);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
私の理解では、jQueryの約束は実行オフに保持すべきであるということであるb
とc
しながら、a
実行され、その後の実行オフに保持c
しながら、b
実行されています。
出力が期待していたのa, b, c
ですが、取得していc, b, a
ます。jQueryのpromiseが計画どおりに実行をブロックしていないという事実を説明するために、これらの遅延( 'a':5000、 'b':2500、 'c':0)を意図的に選択したことに注意してください。
何が欠けていますか?期待される動作を得るためにコードをどのように変更する必要がありますか?
あなたが間違っているのは、約束が実行を妨げると考えることです。そうではありません。promiseは、コールバック関数を作成するためのもう1つの方法です。JavaScriptがネイティブに提供する以上の魔法を追加することはありません。(私はアドレッシングいないよasync
/await
すべてのコールバックが呼び出される前に完了するまで、あなたのコードの実行のすべて、ここでは単に「伝統的な」JavaScriptを。)。
それはあなたが問題にぶつかっているところです。あなたのwhile
ループが完了するまで実行さこれまで呼び出されます、あなたのキューの機能のいずれかの前に:
while (queue.length > 0) {
d = d.then(queue.shift()); // you don't need the `.done`
}
あなたがしているように複数の関数がタイムアウトで呼び出されるようにしたい場合、それを行う最良の方法はsetTimeout()
、あなたのコードが今しているように、すべての呼び出しを一気に実行しないことです。代わりに、各callback
関数に次の関数を開始させsetTimeout()
ます。このようにすると、いつでも保留中のタイムアウトは1つだけになり、タイムアウトが発生すると、次のタイムアウトが開始されます。
私は何年も前にこれと呼ばれるjQueryプラグインを作成しましたslowEach
。(実際にはjQueryに依存せず、同じ手法がjQuery以外のコードでも機能します。)
コードはpromiseを使用しません(数年前に作成されます)が、promiseを使用する場合でも、従来のコールバックを使用する場合でも、原則は同じです。単一のsetTimeout()
から始めて、そのコールバック関数が呼び出されたら、次のを開始しsetTimeout()
ます。これにより、単純なwhile
ループで期待していた方法でタイムアウトがシーケンスされます。
元のslowEach()
コードはこの回答にあります。それ以来、何人かの人々がコードを改善してきました。特に、これはコールバックを追加するバージョンでonCompletion
あり、配列全体が処理されたときに別のコールバックを取得します。
このコードはpromiseを使用していませんが、さらに重要なことに、機能します。:-) promiseを使用するようにコードを適応させることは興味深い演習です。
ただし、JavaScriptが次のコード行を実行する前に、Promiseが実行されるのを待つとは限りません。あなたが使用している場合を除きasync
/ await
、あなたがしているランニングは通常の何でもループ- 、while
、for
何でも-常に前に完了するまで実行されます任意の通常のコールバックや約束- -コールバックの実行を取得します。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加