对ajax请求进行排序

Sco*_*den 63 javascript queue ajax jquery design-patterns

我发现有时我需要迭代一些集合并为每个元素进行ajax调用.我希望在转移到下一个元素之前返回每个调用,这样我就不会向服务器发送请求 - 这通常会导致其他问题.我不想将异步设置为false并冻结浏览器.

通常这涉及设置某种迭代器上下文,我逐步通过每个成功回调.我认为必须有一个更简洁的方式?

有没有人有一个聪明的设计模式,如何通过一个集合为每个项目制作ajax调用整齐地工作?

gna*_*arf 111

jQuery 1.5+

我开发了一个$.ajaxQueue()使用了插件$.Deferred,.queue()$.ajax()也传回一个承诺的请求完成时得到解决.

/*
* jQuery.ajaxQueue - A queue for ajax requests
* 
* (c) 2011 Corey Frang
* Dual licensed under the MIT and GPL licenses.
*
* Requires jQuery 1.5+
*/ 
(function($) {

// jQuery on an empty object, we are going to use this as our Queue
var ajaxQueue = $({});

$.ajaxQueue = function( ajaxOpts ) {
    var jqXHR,
        dfd = $.Deferred(),
        promise = dfd.promise();

    // queue our ajax request
    ajaxQueue.queue( doRequest );

    // add the abort method
    promise.abort = function( statusText ) {

        // proxy abort to the jqXHR if it is active
        if ( jqXHR ) {
            return jqXHR.abort( statusText );
        }

        // if there wasn't already a jqXHR we need to remove from queue
        var queue = ajaxQueue.queue(),
            index = $.inArray( doRequest, queue );

        if ( index > -1 ) {
            queue.splice( index, 1 );
        }

        // and then reject the deferred
        dfd.rejectWith( ajaxOpts.context || ajaxOpts,
            [ promise, statusText, "" ] );

        return promise;
    };

    // run the actual query
    function doRequest( next ) {
        jqXHR = $.ajax( ajaxOpts )
            .done( dfd.resolve )
            .fail( dfd.reject )
            .then( next, next );
    }

    return promise;
};

})(jQuery);
Run Code Online (Sandbox Code Playgroud)

jQuery 1.4

如果您正在使用jQuery 1.4,则可以利用空对象上的动画队列为您的元素的ajax请求创建自己的"队列".

您甚至可以将其纳入您自己的$.ajax()替代品中.这个插件$.ajaxQueue()使用jQuery的标准'fx'队列,如果队列尚未运行,它将自动启动第一个添加的元素.

(function($) {
  // jQuery on an empty object, we are going to use this as our Queue
  var ajaxQueue = $({});

  $.ajaxQueue = function(ajaxOpts) {
    // hold the original complete function
    var oldComplete = ajaxOpts.complete;

    // queue our ajax request
    ajaxQueue.queue(function(next) {

      // create a complete callback to fire the next event in the queue
      ajaxOpts.complete = function() {
        // fire the original complete if it was there
        if (oldComplete) oldComplete.apply(this, arguments);

        next(); // run the next query in the queue
      };

      // run the query
      $.ajax(ajaxOpts);
    });
  };

})(jQuery);
Run Code Online (Sandbox Code Playgroud)

示例用法

所以,我们有<ul id="items">一些<li>我们想要复制(使用ajax!)的<ul id="output">

// get each item we want to copy
$("#items li").each(function(idx) {

    // queue up an ajax request
    $.ajaxQueue({
        url: '/echo/html/',
        data: {html : "["+idx+"] "+$(this).html()},
        type: 'POST',
        success: function(data) {
            // Write to #output
            $("#output").append($("<li>", { html: data }));
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

jsfiddle示范 - 1.4版

  • 任何知道队列的方法都是完全空/完全触发动作? (2认同)

Tho*_*din 13

使用延期承诺的快速小解决方案.虽然这使用jQuery $.Deferred,但任何其他人都应该这样做.

var Queue = function () {
    var previous = new $.Deferred().resolve();

    return function (fn, fail) {
        return previous = previous.then(fn, fail || fn);
    };
};
Run Code Online (Sandbox Code Playgroud)

用法,调用创建新队列:

var queue = Queue();

// Queue empty, will start immediately
queue(function () {
    return $.get('/first');
});

// Will begin when the first has finished
queue(function() {
    return $.get('/second');
});
Run Code Online (Sandbox Code Playgroud)

请参阅示例,并对异步请求进行并排比较.