Javascript 在触发一系列ajax请求时对其进行排队
我希望使用JQuery对一系列AJAX请求进行排队。 假设有一个函数updateImage(),它根据用户单击的按钮向服务器查询URL,并返回指向图像的链接。 服务器记录imageId,浏览器显示图像。此应用程序要求按发送顺序触发成功顺序回调函数(以便浏览器显示与用户单击顺序对应的图像) 举例说明:Javascript 在触发一系列ajax请求时对其进行排队,javascript,jquery,ajax,Javascript,Jquery,Ajax,我希望使用JQuery对一系列AJAX请求进行排队。 假设有一个函数updateImage(),它根据用户单击的按钮向服务器查询URL,并返回指向图像的链接。 服务器记录imageId,浏览器显示图像。此应用程序要求按发送顺序触发成功顺序回调函数(以便浏览器显示与用户单击顺序对应的图像) 举例说明: //User a number of buttons in quick succession $(".button").click(function(){ var imageId = $(t
//User a number of buttons in quick succession
$(".button").click(function(){
var imageId = $(this).attr("id");
updateImage(imageId);
});
//Ajax success callbacks need to run in the order of the clicks
function updateImage(imageId) {
$.ajax({
url: /someurl,
data: imageId,
success: successFunction //this function will update the DOM
});
}
我考虑过$.ajaxStop,但问题是还有其他AJAX函数,我不想因为这个updateImage函数而暂停或排队。我还研究了$.when,但这允许您链接已知数量的ajax调用执行,但我不确定用户将单击多少次-我不确定这是否适用于这里。这就完成了您想要的。基本上,下面的代码正是您想要的,一个包含异步ajax请求的同步事件队列。确保在
updateImage
函数中填写成功所需的任何操作
编辑2015年12月11日
@_benng在twitter上指出,我最初的版本是一个末日金字塔。
他是对的,因为队列可能会发生变异,导致
索引不一致问题(在触发click事件处理程序时数组更改长度,
导致在click handler/ajax回调中使用时索引发生更改)
一个简单的补救方法是将队列复制到一个临时变量并对其进行处理,只需截断
在没有变异的情况下安全地排队。我试图涵盖所有我能想到的边缘案例,但可能有一些我错过了。无论如何,快乐的编码。如果出现问题,如果您能想出如何在javascript中实现悲观锁定,您可能希望使用悲观锁定。我尝试过很多次,但都失败了
$(function(){
var queue = [],
var q = {},
var t;
$(".button").click(function(){
var index = queue.push({
id: imageId,
completed: false
});
$.ajax({
url: /someurl,
data: imageId,
success: function(data){
//since length is 1 based and index is 0 based
//queue.length > index ~ queue.length >= index+1
if(queue.length > index){
queue[index].completed = true;
$(q).trigger('completed');
}
}
});
});
$(q).on('completed',function(){
if(typeof t === 'number') clearTimeout(t);
//copy queue to a temporary array.
var copy = (function(){ return queue.slice(); }());//for the paranoid perform safe "copy" of array
var copy_len = copy.length;//starting copy length
t = setTimeout(function(){
while(copy.length > 0){
if(copy[0].completed == false) break;
var item = copy.shift();
updateImage(item.id);
}
//if queue length has changed,we could mistakenly delete unprocessed items by truncating array
//only destroy queue if copy.length === 0 and queue.length equals starting copy length
if(copy.length===0 &©_len===queue.length){
queue.length = 0; //truncate queue only when it is "safe"
}
},100);
});
function updateImage(imageId)
{
//do whatever you need to do here on completion.
}
});
你弄明白了吗?我还在努力。我确实看过你的建议——理想情况下,我希望它在没有设置超时的情况下工作,这样迭代就可以在不等待的情况下重复,但我在问题中没有提到。你为什么接受这个答案?此外,我的答案依赖于setTimeout仅作为速率限制器,即(快速单击5个按钮仅在上次启动该函数。@我将其标记为正确,因为setTimeout不适合我的特殊需要(我在问题中没有明确说明),对于其他人来说,它是有效的,而且简洁明了。谢谢!twitter上的一位用户指出,在某些情况下,这可能会导致事情发生混乱。我稍后会对答案进行修正。