队列AJAX调用

时间:2011-01-25 18:48:37

标签: javascript jquery-ui jquery-plugins jquery

您好我正在做一个横向滚动网站,例如:http://vanityclaire.com/

然而,在加载主页之后,我不是拥有一个大的HTML文件,而是使用jQuery .load()在家里的孩子们中。

目前我为每个div和ajax in the url位于标题中。但是AJAX返回乱序,并且当我添加更多页面时,并不喜欢使用30多个http://请求 spanging 服务器。

如何同步执行AJAX调用,即等待第一个请求再转发,或者甚至一次发送两个。

我一直在寻找,无法弄清楚我需要什么。

这是我的HTML:

<div id="mainLayout" class="fullwidth scrollArea">
    <div class="scrollItems">
      <div id="page-1" class="scrollItem" title="/">
        <div>HOME PAGE CONTENT</div>
      </div>
      <div id="page-2" class="scrollItem" title="/Page2.html">
        <div class="loading"> </div>
      </div>
      <div id="page-3" class="scrollItem" title="/Page3.html">
        <div class="loading"> </div>
      </div>

      <div id="page-4" class="scrollItem" title="/Page4.html">
        <div class="loading"> </div>
      </div>
      <div id="page-5" class="scrollItem" title="/Page5.html">
        <div class="loading"> </div>
      </div>
    </div>
  </div>

我的JS:

function s_loadingInitialPages() {
    var loadingItems = new Array();
    $(".scrollArea .scrollItem").each(function () {
        if ($(this).attr('title') != '/') {
            var oDelem = $(this);
            loadingItems.push(oDelem);
            //alert('test');
        }
    });

    for (i = 0; i < loadingItems.length; i++) {
        // title attribute is the URL to get
        var ajaxURL = loadingItems[i].attr("title") + '?ajaxPageContent=';
        $(loadingItems[i]).load(ajaxURL);

    }
}

是否有插件我可以继续向队列添加函数,让它处理它?<​​/ p>

2 个答案:

答案 0 :(得分:18)

诀窍是使用回调。你进行一次ajax调用,并在成功回调时创建下一个调用。

要做到这一点,只需将它们全部添加到队列中并在其周围放置一个包装器,逐个发送它们。

我几天前写了一篇文章。我会在一秒钟内向您展示一个实现。

// Buffer class. Has a public append method that expects some kind of Task.
// Constructor expects a handler which is a method that takes a ajax task
// and a callback. Buffer expects the handler to deal with the ajax and run
// the callback when it's finished
function Buffer(handler) {
    var queue = [];

    function run() {
        var callback = function () {
             // when the handler says it's finished (i.e. runs the callback)
             // We check for more tasks in the queue and if there are any we run again
             if (queue.length > 0) {
                  run();
             }
        }
        // give the first item in the queue & the callback to the handler
        handler(queue.shift(), callback);
    } 

    // push the task to the queue. If the queue was empty before the task was pushed
    // we run the task.
    this.append = function(task) {
        queue.push(task);
        if (queue.length === 1) {
            run();
        }
    }

}

// small Task containing item & url & optional callback
function Task(item, url, callback) {
    this.item = item;
    this.url = url;
    this.callback = callback
}

// small handler that loads the task.url into the task.item and calls the callback 
// when its finished
function taskHandler(task, callback) {
    $(task.item).load(task.url, function() {
        // call an option callback from the task
        if (task.callback) task.callback();
        // call the buffer callback.
        callback();
    });
}

// create a buffer object with a taskhandler
var buffer = new Buffer(taskHandler);

for (i = 0; i < loadingItems.length; i++) {
    // title attribute is the URL to get
    var ajaxURL = loadingItems[i].attr("title") + '?ajaxPageContent=';
    buffer.append(new Task(loadingItems[i], ajaxURL));
}

为代码墙道歉。只需实现自己的任务和处理程序。只要处理程序在处理完任务时调用第二个参数(回调),缓冲区就会起作用。

然后只传递一个任务和一个处理程序。处理程序执行ajax并在ajax返回时从缓冲区调用回调。

对于您的具体示例,如果您的加载需要很长时间,那么这将花费很长时间来加载所有30. ajax的目的是让服务器并行执行。

在您的情况下,一个更好的解决方案是发出30个请求然后捕获结果并确保您的ajax调用的结果仅按顺序附加到dom。这涉及使用$ .ajax并以某种方式添加跟踪订单。

这样服务器就会尽可能快地完成它,一旦你得到它,你就可以按顺序服务它。或者,如果你做的事情很快,那么在缓冲区中排队它们就没有任何惩罚。

答案 1 :(得分:0)

大多数浏览器可以同时处理对单个域的6个或更多个ajax请求 http://www.browserscope.org/?category=network&v=top

如果您的脚本一次发出30个ajax请求,前6个请求将很快完成。之后,浏览器可能会开始分配长达5秒的任意等待时间。 Chrome就是这种行为的一个典型例子。

请求1-6在5毫秒内返回。

请求7-12在5,005毫秒内返回。

请求11-18在10,005毫秒内返回。

请求19-24在15,005毫秒内返回。

请求25-30在20,005毫秒内返回。

我建议构建一个函数回调队列来处理所有应用程序的ajax请求,并且一次处理不超过6个。

&#13;
&#13;
var ajaxCownt = (ajaxCownt == null ? 0 : ajaxCownt);  // Make limit globally accessible.
var ajaxKue = (ajaxKue == null ? [] : ajaxKue);  // Make queue globally accessible.

function doMyAjaxRequest() {
console.log("doing ajax request.");
// Implement ajax request, here.
}

for (var i = 1;i <= 30;i++) {
ajaxKue.push( function() { doMyAjaxRequest() } ); // Add request to queue.
}

while (ajaxCownt != null && ajaxCownt < 6 && ajaxKue != null && ajaxKue.length && ajaxKue.length > 0) {
ajaxCownt++;
console.log("incrementing pending ajax requests counter by 1.");
ajaxKue.shift().call();
};

// Register an event to detect when an ajax request completes.
// Allow for an additional ajax request to be processed.
$( document ).ajaxComplete(function() {
    if (ajaxCownt && ajaxCownt > 0) {
        ajaxCownt--;
        console.log("decrementing pending ajax requests counter by 1.");
    }
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
&#13;
&#13;
&#13;