5

JavaScript/jQueryで任意の数のオプションの関数呼び出しをキューに入れようとしています。たとえば、2番目(または3番目、4番目など)の関数またはAJAX呼び出しを実行する前に、ユーザーが認証され、Cookieが設定されていることを確認する必要がある場合があります。

最近追加されたjQuery.Deferredを使用してこれを行うことを検討しましたが、呼び出しがどの順序で実行されるかは問題ではないことがわかりました(真の非同期スタイル)。また、Deferredインスタンスが解決されると、それを元に戻すことはできないことを読みました。

これが私が今これに取り組んでいるところです。最初は、Deferredインスタンスを解決するように設定し、オプションの関数がスタックに表示された場合は解決しないことを考えていました。

var d = $.Deferred(),
    chained = d,
    d.resolve(),
    div = extra.find( "div:first" );

if ( extra.attr( "requires-auth" ) != undefined && !config.user_is_authenticated )
  chained = chained.pipe( authenticate );

if ( div.length )
  chained = chained.pipe( prepareExtra( div ) );

// When the two optional methods are resolved, show the content
chained.done( function() {
  extra.fadeIn( 500 )
} );

私の質問は、純粋なJavaScript / jQueryでAJAX呼び出しをキューに入れる(0からN)ための最良の方法は何ですか?(プラグインを使用せずに)。

タク!

編集2:解決しました! これのいくつかの実用的な例を次に示します。1つはAJAXなしで、もう1つは https://gist.github.com/1021429https://gist.github.com/1021435を使用しています

4

4 に答える 4

7

最後に、最初のDeferredを解決してみてください。

var d = $.Deferred(),
    chained = d;

// optionally chain callbacks with chained = chained.pipe
if (condition) {
    chained = chained.pipe(function () {
        return $.ajax({...}); // Must return a new Promise
    });
}

chained.done(function () {
    // all chains should be processed now
});

d.resolve(); // finally, resolve the initial Deferred
于 2011-06-09T15:12:22.657 に答える
0

シーケンス ヘルパーを使用します。

https://github.com/michiel/asynchelper-js/blob/master/lib/sequencer.js

同様の問題がありました: jQuery Ajax / .each コールバック、ajax が完了する前に次の 'each' が起動する

于 2011-06-09T15:50:40.943 に答える
0

過去に、ajax 呼び出しで他のスクリプトを返すことでこれを処理しました。私にとって、それが最善の解決策です。

ただし、純粋な js アプローチが必要だったので、試してみます。

var ScriptQueue = {
    scripts: [],
    readyToProcess: false,
    timer: null,
    stopTimer: function() {
        clearTimeout(ScriptQueue.timer);
        ScriptQueue.timer = null;
    },
    queue: function(functionToQueue) {
        ScriptQueue.stopTimer();
        ScriptQueue.scripts.push(functionToQueue);
        ScriptQueue.processNext();
    }, 
    processNext: function() {
       if (!readyToProcess || ScriptQueue.scripts.length == 0) {
           ScriptQueue.timer = setTimeout(ScriptQueue.processNext, 30000); // try again in 30 sec
       } else {
           ScriptQueue.stopTimer();
           var _function = ScriptQueue.scripts.shift();
           _function.call();
           ScriptQueue.processNext();
       }
    }
}

$(function(){

    // queue some stuff

    $('a').each(function() {
        ScriptQueue.queue(function() {
            console.info("running some link action");
        } );
    });

    // authorization
    $.ajax({
        url: yourURL
        success: function(data) {
           if (data == "correct response") {
               ScriptQueue.readyToProcess = true;
               ScriptQueue.processNext();
           }
        }
    })


});

これが機能するかどうかはわかりませんが(テストされていません)、解決策の代替案を提案したかったのですDeferred(有望に見えます)。たぶんそれはさらなる議論につながり、無視されるかもしれません。

于 2011-06-09T15:53:02.557 に答える
0

テストされていませんが、jQuery.whenはうまく動作するはずです:

var q = [];
function queue(promise, callback) {
    var ready = $.when.apply($, q); // resolves when all current elements 
                                   // of the queue have resolved
    q.push(promise);
    ready.done(function() {
        q.shift();
        var arg = Array.prototype.pop.call(arguments);
        callback.call(promise, arg);
    });
}
于 2011-06-09T17:27:27.417 に答える