我发现有时我需要迭代一些集合并为每个元素进行ajax调用。我希望每个调用在返回到下一个元素之前都返回,这样我就不会对服务器进行请求处理- 这通常会导致其他问题。而且我不想将async设置为false并冻结浏览器。
通常,这涉及设置某种迭代器上下文,该迭代器上下文将在每次成功回调时进入。我认为必须有一种更清洁,更简单的方法?
有没有人有一个聪明的设计模式,说明如何通过一个集合为每个项目进行ajax调用而使它们整齐地工作?
我开发了一个$.ajaxQueue()使用了插件$.Deferred,.queue()和$.ajax()也传回一个承诺,那就是请求完成时得到解决。
$.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);
如果您使用的是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);
因此,我们有一个<ul id="items">其中的一些<li>我们想要复制(使用ajax!)到<ul id="output">
<ul id="items">
<li>
<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 })); } }); });
的jsfiddle示范 - 1.4版本