Javascript 在jQuery中排队可选AJAX/函数调用($.Deferred)?

Javascript 在jQuery中排队可选AJAX/函数调用($.Deferred)?,javascript,jquery,jquery-deferred,Javascript,Jquery,Jquery Deferred,我希望在JavaScript/jQuery中对任意数量的可选函数调用进行排队。例如,在运行第二个(或第三个、第四个等)函数或AJAX调用之前,我可能需要确保对用户进行身份验证并设置cookie 我研究了最近添加的jQuery.Deferre,但发现调用的顺序并不重要(真正的异步风格)。此外,我还了解到,一旦解决了延迟实例,就不可能取消解决它 这就是我目前的处境。最初,我考虑将延迟实例设置为已解析,然后在堆栈中出现可选函数时取消解析 var d = $.Deferred(), chaine

我希望在JavaScript/jQuery中对任意数量的可选函数调用进行排队。例如,在运行第二个(或第三个、第四个等)函数或AJAX调用之前,我可能需要确保对用户进行身份验证并设置cookie

我研究了最近添加的jQuery.Deferre,但发现调用的顺序并不重要(真正的异步风格)。此外,我还了解到,一旦解决了延迟实例,就不可能取消解决它

这就是我目前的处境。最初,我考虑将延迟实例设置为已解析,然后在堆栈中出现可选函数时取消解析

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中排队(0到N)AJAX调用的最佳方式是什么?(不使用插件)

编辑2:已解决 下面是一些这样的工作示例,一个不使用AJAX,另一个使用:

尝试将初始延迟作为最后一件事来解决:

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
使用序列助手:


我有一个类似的问题:

我过去通过让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();
           }
        }
    })


});
我不知道这是否有效(未经测试),但我想建议一种可能的替代方案,以取代
延迟
解决方案(看起来很有希望)。可能会导致进一步的讨论,可能会被忽略。

未测试,但应该可以很好地解决此问题:

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);
    });
}

为什么要在第3行中立即解析
d
?当时的想法是,如果我不立即解析d,那么就永远不会完成。如果chained再也没有收到任何函数,那么.done仍将启动。这将正确地启动.done函数,而不是等待chained完成。是的,但您需要在链函数中返回新的承诺。更新了我的答案,使之更加具体。即使每个函数返回的承诺是唯一的,它仍然是异步的,不是吗?据我所知,它不会在运行第一个方法时停止执行,而是等待响应,然后尝试第二个方法。在这一点上我可能错了,但它似乎不起作用(我需要看看你的函数是如何实现的。它们需要异步才能工作。如果你粘贴更多的代码,这会很有帮助。
pipe
接受函数,而不是承诺。请看我的主要评论。我可能会在未来几天有空的时候试一试!谢谢你的提议。试一试,5行和ion和Github上的完整库。两者似乎都不起作用,但我可能没有正确理解。我如何将参数提供给正在排序的函数?为什么函数(callback)和callback();是必需的?(提前感谢!)这似乎是一个很好的方法,但我对实现有点困惑。如何将函数推送到q,以及如何/何时运行队列函数?您可以这样使用:
queue($.get(url),function(){/*process AJAX response*/})
。这将获取由$返回的承诺对象。get,将其推送到队列中,创建一个新的承诺对象,当队列中的所有内容都已解决时,该对象将得到解决,并在新承诺得到解决时调用回调。因此,您对承诺/延迟和回调使用
queue
,当承诺都已解决时,回调将触发nd前面传递给
队列的所有其他承诺都已解决(尽管这只有在成功解决的情况下才有效)。我可能错过了一些东西,但我不确定这将如何工作。我创建了一个用于测试目的的JSFIDLE(),它与此代码有一个预期问题。即,$.when()始终查看它被传递的内容,如果它不符合承诺或延迟,则它会创建一个新的延迟,并使用传递的内容立即解析它。这似乎是它在第三行中得到数组时所做的。它会立即解析作为结果传递的q。@John:对不起,这应该是
应用
,而不是调用
。修复了它。