2

一連のカスケード ドロップダウン選択リストをサポートする ajax リクエストのチェーンがあります。1 番目のドロップダウンで値を選択すると、2 番目の値を設定するためのリクエストが起動され、それが完了すると (そしてドロップダウンが入力されると)、3 番目のドロップダウンを設定するために次のリクエストが起動されます。

これらのリクエスト チェーンの形成方法にはいくつかのバリエーションがあるため、jQuery Deferred オブジェクトを使用してリクエストを組み立てたいと考えていました。

2 番目のリクエストを最初のリクエストにチェーンする方法はわかりますが、3 番目のリクエストを 2 番目にチェーンする方法がわかりません。

function Step1() { return $.ajax(<foo>);}
function Step2() { return $.ajax(<foo>);}
function Step3() { return $.ajax(<foo>);}

$(function() {
   Step1().then(Step2).then(Step3);
});

その意図は、Step2 が解決されたときに Step3 がトリガーされることですが、によって返される遅延オブジェクトは.then(Step2)Step1 からのものであるため、Step3 は Step1 へのコールバックとして追加されます。

この jsFiddle sampleをご覧いただければ、私がやろうとしていることはより明確になると思います。 編集これは、より明確にするために2番目の呼び出しに遅延が追加された同じスクリプトです。

4

3 に答える 3

3
$(function() {
    $.when(Step1).then(function() {
         $.when(Step2).then(Step3);
    });
});

エラー処理については、Stepn を次のように書き換えることをお勧めします。

function Stepn() { 
    return $.ajax(<foo>).fail(function() {
         // handle failure
    });
}

この形式でコールバックを使用すると、必要なことを行うことができます。5 つ以上のステップがある場合、インデントが混乱するため、このためのキューを作成する価値があるかもしれません。

これがライブの例です

var Queue = function() {
    var q = [];
    var that = this;

    // If items in queue then run them.
    function moveNext() {
        if (q.length > 0) {
            that.runItem();
        }
    }

    // run first item in queue
    this.runItem = function() {
        // get item
        var item = q.shift();
        // when deferred object then run then ...
        $.when(item.item).then([item.options.done, function() {
            // item finished, move to next.
            moveNext();
        }], [item.options.fail, function() {
            // if run item always then move next on failure.
            if (item.options.always) {
                moveNext();
            }
        }]);
    };

    this.add = function(def, options) {
        // if array then call add on each item in array
        if ($.isArray(def)) {
            for (var d in def) {
                this.add(d, options);
            }
            // return as we are done.
            return this;
        }
        // push item onto array
        q.push({
            item: def,
            options: options
        });
        // if items & not delay then run item.
        if (q.length === 1 && !options.delay) {
            this.runItem();
        }
        // enable jQuery style chaining \o/
        return this;
    };
};

Queue.add([def, def, ...], options)遅延アイテムまたは遅延アイテムの配列をキューに追加します。単一の遅延アイテムまたは配列のいずれかで使用できます。オプションマップは次のとおりです

{
    "delay" : Boolean, // if true do not run the item in the queue after appending it.
    "done" : Function, // optional done call back
    "fail" : Function, // optional fail call back
    "always": Boolean // if true run the next item in the queue even if this item fails.
}

Queue.runItem、キュー内の次のアイテムを実行する関数。内部で呼び出され、遅延プロパティと連結して手動で使用できます。

于 2011-04-02T17:59:40.123 に答える
0

私たちは幸運で、タイムラインにある程度の柔軟性がありました。.pipe()jQuery 1.6 で遅延オブジェクトに追加されたチェーンを使用することになりました。

助けてくれてありがとう!

于 2011-05-03T18:37:51.210 に答える
0

James Coglanのブログ シリーズに触発されて、最近これに取り組み始めました (こちらの質問を参照してください)。

しばらく「モナド」をいじった後、遅延オブジェクトを一緒に「連鎖」できればいいのにと思うようになりました。問題は、「完了」が新しいオブジェクトではなく、同じ遅延オブジェクトを返すことです。

しばらくの間 jquery コードを参照しましたが、Deferred または _Deferred コードに何かを挿入する方法はないと考えました。ただし、独自のオブジェクトをパラメーターとして関数に注入すること可能です。したがって、チェーン可能なプロミスを生成する関数を作成すると...promise()

var Chainable = function Chainable() {
     return {
         chain : function(next) { //next: another function which returns Deferred
                 var newDef = $.Deferred(); //we resolve this when next is done
                 //next line: call next with (a||null) for method-tolerance
                 this.done(function(a) { next(a||null).done(newDef.resolve); });
                 return newDef.promise(Chainable());
         }
     };
 }

...次に、それを使用してスタイルをポンピングできます。

var asyncMessage = function(msg) {
    var dfd = new jQuery.Deferred();
    setTimeout(function() { dfd.resolve(msg); }, 1000);
    return dfd.promise(Chainable());
};

asyncMessage("Chained:A")
     .chain(function(m) { return asyncMessage(m + "B"); })
     .chain(function(m) { return asyncMessage(m + "C"); })
     .done(log); // -> outputs "ABC"

「前/後」のコード サンプルについては、こちらの jsfiddle を参照してください: http://jsfiddle.net/Benjol/DjrRD/

于 2011-04-17T10:06:38.700 に答える