我正在寻找在JavaScript / jQuery中排队任意数量的可选函数调用。例如,在运行第二个(或第三个,第四个等)函数或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中排队(0到N)AJAX调用的最佳方法是什么? (不使用插件)。
德!
编辑2:已解决! 以下是一些有用的例子,一个没有AJAX,一个有: https://gist.github.com/1021429 https://gist.github.com/1021435
答案 0 :(得分: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
答案 1 :(得分:0)
使用序列助手:
https://github.com/michiel/asynchelper-js/blob/master/lib/sequencer.js
我遇到了类似的问题:jQuery Ajax / .each callback, next 'each' firing before ajax completed
答案 2 :(得分: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
解决方案(看起来很有希望)。也许它会导致进一步的讨论,也许会被忽视。
答案 3 :(得分: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);
});
}