【问题标题】:Queuing a series of ajax requests as they are triggered在触发一系列 ajax 请求时对其进行排队
【发布时间】:2015-11-15 12:34:09
【问题描述】:

我希望使用 JQuery 对一系列 AJAX 请求进行排队。 假设有一个函数 updateImage() 根据用户单击的按钮向服务器查询 URL,并返回指向图像的链接。 服务端记录imageId,浏览器显示图片。本应用要求成功回调函数按照发送顺序触发(以便浏览器显示与用户点击顺序对应的图片)。

举例说明:

//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,但问题是我不想因为这个 updateImage 函数而暂停或排队其他 AJAX 函数。我还查看了 $.when,但这允许您链接已知数量的 ajax 调用执行,但我不确定用户会点击多少次 - 我不确定这是否适用于此。

【问题讨论】:

  • 你搞定OP了吗?
  • @r3wt 我还在努力。我确实看过您的建议 - 理想情况下,我希望它在没有 setTimeout 的情况下工作,以便迭代重复而无需等待,但我没有在问题中提到这一点。
  • 你为什么接受这个答案?另外,我的答案仅依赖于 setTimeout 来充当速率限制器,即(快速单击 5 个按钮只会在最后一次触发该功能。
  • @r3wt 我将其标记为正确,因为除了 setTimeOut 不符合我的特定需求(我在问题中没有明确说明)之外,对于其他任何人来说,它工作,并且干净简单。谢谢!

标签: javascript jquery ajax


【解决方案1】:

这完成了你想要的。基本上,下面的代码完全符合你的要求,一个带有异步 ajax 请求的同步事件队列。请务必在updateImage 函数中填写成功后需要执行的任何操作。

2015 年 11 月 12 日编辑

推特上的@_benng 指出我的原始版本是pyramid of doom。 他是对的,因为队列有可能发生变异导致 不一致的索引问题(在点击事件处理程序触发时数组更改长度, 导致在点击处理程序/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 &&copy_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.
    }

});

【讨论】:

  • 一位推特用户指出,在某些情况下,这可能会导致事情发生混乱。稍后我将修复答案。
猜你喜欢
  • 2011-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多