2013-02-11 31 views
5

我需要使用有限的流进行顺序异步ajax请求。截至目前,我只能在Web服务器上占用一个流,因此我只能在一次做一个Ajax请求。如何使用给定数量的流执行顺序异步ajax请求

我有以下功能,可以帮助我,当我被允许一次只能使用一个流。

function initiateChain() { 
    var i = 0; 
    var tasks = arguments; 
    var callback = function() { 
     i += 1; 
     if (i != tasks.length) { 
     tasks[i](callback); //block should call callback when done otherwise loop stops 
     } 
    } 
    if (tasks.length != 0) { 
     tasks[0](callback); //initiate first one 
    } 
    } 

说,如果我有三个AJAX辅助功能

function getGadgets(callback) { 
     //ajax call 
     callback(); // I call this in complete callback of $.ajax 
} 

function getBooks(callback) { 
     //ajax call 
     callback(); // I call this in complete callback of $.ajax 
} 

function getDeals(callback) { 
     //ajax call 
     callback(); // I call this in complete callback of $.ajax 
} 

以下调用确保不超过1个AJAX请求从该客户端进行

initiateChain(getGadgets, getBooks, getDeals); 

现在我需要加强initiateChain以支持任意数量的流。假设我被允许使用2或n个流,我想知道如何在不改变Ajax帮助函数getGadgets,getDeals,getDeals的情况下这样做。

总之,我有一组函数N,在这种情况下getGadgets,getDeals和getDeals(| N | = 3),每个函数都需要连接到Web服务器。目前,我一次只能执行一个请求,所以启动链接函数按顺序调用这三个方法。如果我有权访问M个连接,我想执行| N |并行运行(最高可达M)。

+1

你的问题到底是什么? – jfriend00 2013-02-11 05:13:11

+0

正如我提到的 我有一组函数N,在这种情况下getGadgets,getDeals和getDeals(| N | = 3),每个函数都需要连接到Web服务器。目前,我一次只能执行一个请求,所以启动链接函数按顺序调用这三个方法。如果我有权访问M个连接,我想执行| N |并行运行(最高可达M)。 – harsha 2013-02-11 07:57:47

回答

14

如果你使用jQuery,那么你可以使用它的.queue方法排队您的ajax调用,然后按顺序执行它们。要运行多个序列,可以将初始出队包装在一个循环中。

function add_api_call_to_queue(qname, api_url) { 
    $(document).queue(qname, function() { 
     $.ajax({ 
      type  : 'GET', 
      async : true, 
      url  : api_url, 
      dataType : 'json', 
      success : function(data, textStatus, jqXHR) { 
       // activate the next ajax call when this one finishes 
       $(document).dequeue(qname); 
      } 
     }); 
    }); 
} 

$(document).ready(function() { 

    var queue_name  = 'a_queue'; 
    var concurrent_calls = 2; 

    // add first AJAX call to queue 
    add_api_call_to_queue(queue_name, '/example/api/books'); 

    // add second AJAX call to queue 
    add_api_call_to_queue(queue_name, '/example/api/dvds'); 

    // add third AJAX call to queue 
    add_api_call_to_queue(queue_name, '/example/api/shoes'); 

    // start the AJAX queue 
    for (i=0;i<concurrent_calls;i++) { 
     $(document).dequeue(queue_name); 
    } 

}) 
+0

谢谢。它按需要工作。 – harsha 2013-07-31 05:28:52

+0

如果它有效,您能否将答案标记为获胜答案。谢谢 – 2013-11-09 08:16:08

+0

这很聪明!非常感谢。 – Kevindra 2014-09-09 22:31:48

1

只要你的回调都是同步这应该为你工作,如果不把你在正确的轨道

var initiateChain = function() { 

    var args = arguments, 
     index = 0, 
     length = args.length, 
     process = function (index) { 

      if (index < length) { 
       $.ajax({ 
        url: '/example.php', 
        complete: function() { 
         // Callbacks get run here 
         args[ index ]; 
         process(++index); 
        } 

       }); 
      } 


     }; 

    if (length) { 
     process(0); 
    } 

}; 

initiateChain(getGadgets, getDeals, getDeals); 
0

感谢@詹姆斯,我得到了线索,从所编辑的内容长度。因此这些调用是异步的Ajax请求。所以这个想法是在创建M个异步调用预先。然后,当每个人完成时,他们会继续这么多。

我做实验和的NodeJS以下initiateChain按预期工作

var calls = []; 

function initiateChain() { 
    var i = 0; 
    var maxSteams = 2; 
    var tasks = arguments; 
    var callback = function() { 
     i += 1; 
     if (i < tasks.length) { 
     tasks[i](callback); //block should call callback when done otherwise loop stops 
     } 
    } 
    if (tasks.length) { 
     i = ((tasks.length > maxSteams) ? maxSteams : tasks.length) - 1; 
     for (var j = 0; j < maxSteams; j+=1) { 
     if (j < tasks.length) { 
      tasks[j](callback); //initiate first set 
     } else { 
      break; 
     } 
     } 
    } 
} 

//test methods 
for(var k = 0; k < 8; k+=1) { 
    calls[k] = (function (message, index) { 
    return function (callback) { 
     var ts = new Date().getTime(); 
     console.log(message + " started - " + ts); 
     setTimeout(function() { 
     ts = new Date().getTime(); 
     console.log(message + " completed - " + ts); 
     callback(); 
     }, index * 1000); 
    }; 
    })("call" + (k+1), (k+1)) 
} 

initiateChain(calls[0], calls[1], calls[2], calls[3], 
    calls[4], calls[5], calls[6], calls[7]); 

在我的实验我得到了以下结果

call1 started - 1360580377905 
call2 started - 1360580377926 

call1 completed - 1360580378937 
call3 started - 1360580378937 

call2 completed - 1360580379937 
call4 started - 1360580379937 

call3 completed - 1360580381945 
call5 started - 1360580381945 

call4 completed - 1360580383946 
call6 started - 1360580383946 

call5 completed - 1360580386959 
call7 started - 1360580386959 

call6 completed - 1360580389950 
call8 started - 1360580389950 

call7 completed - 1360580393972 

call8 completed - 1360580397959