each() 函数中的多个 ajax 调用.. 然后在所有这些都完成后执行一些操作?
Posted
技术标签:
【中文标题】each() 函数中的多个 ajax 调用.. 然后在所有这些都完成后执行一些操作?【英文标题】:Multiple ajax calls inside a each() function.. then do something once ALL of them are finished? 【发布时间】:2012-02-02 07:20:42 【问题描述】:让我稍微解释一下我的代码(如果有问题请见谅,我刚刚从头开始编写这个示例,它与我目前的非常接近)。
HTML:
<form id="form">
<!-- Friend 1 -->
Name 1: <input type="text" name="friendName1" id="friendName1" class="friendName" value=""><br />
Email 1: <input type="text" name="friendEmail1" id="friendEmail1" value=""><br /><br />
<!-- Friend 2 -->
Name 2:<input type="text" name="friendName2" id="friendName2" class="friendName" value=""><br />
Email 2:<input type="text" name="friendEmail2" id="friendEmail2" value=""><br /><br />
<!-- Friend 3 -->
Name 3:<input type="text" name="friendName3" id="friendName3" class="friendName" value=""><br />
Email 3:<input type="text" name="friendEmail3" id="friendEmail3" value=""><br /><br />
<!-- Friend 4 -->
Name 4:<input type="text" name="friendName4" id="friendName4" class="friendName" value=""><br />
Email 4:<input type="text" name="friendEmail4" id="friendEmail4" value=""><br /><br />
<!-- Submit -->
<input name="submit" type="submit" value="Submit">
</form>
JS:
$("#form").submit(function()
$(".friendName[value!='']").each(function()
var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName','');
if($("#"+idEmail+"[value!='']").length > 0)
var name = $(this).val();
var email = $("#"+idEmail).val();
// Submit the ajax request
$.ajax(
type: 'POST',
url: 'ajax/url',
data:
name: name,
email: email
,
success: function(json)
// Log a console entry if our ajax request was successful
console.log(name + " was submitted via ajax");
);
);
// Redirect the user to the thank you page
setTimeout( function() window.location= '/thanks'; , 2000 );
);
JSFiddle(重定向已移除,ajax 调用替换为小提琴的控制台日志)
http://jsfiddle.net/cM5PX/
html 是一个简单的表单,带有朋友姓名和朋友电子邮件输入字段。
JS 有一个 each 函数,如果 name 和关联的 email 有值,它会运行一个 ajax 调用。
我需要一种方法让这些 ajax 调用运行(可能有 1 个循环,可能有 15 个),然后在它们全部完成后,重定向到新页面。
我目前的做法很糟糕,因为所有的 ajax 调用都没有在页面重定向之前完成运行。
我可以做些什么来改善它?它需要是万无一失的,并且只有在所有 ajax 调用完成后才重定向(成功或错误,没关系 - 它只需要在完成后重定向)。
我尝试过使用async: false
,但似乎没有什么不同。
我曾考虑在每个函数中放置一个计数器,在 ajax 成功函数中放置一个计数器,如果它们都匹配,则进行重定向,但我正在寻找一些更有经验的指导。
【问题讨论】:
【参考方案1】:使用deferred objects:
$("#form").submit(function(e)
e.preventDefault();
var calls = [];
$(".friendName[value!='']").each(function()
// Submit the ajax request
calls.push($.ajax(
type: 'POST',
url: 'ajax/url',
data:
name: name,
email: email
,
success: function(json)
// Log a console entry if our ajax request was successful
console.log(name + " was submitted via ajax");
));
);
$.when.apply($, calls).then(function()
window.location= '/thanks';
);
);
【讨论】:
这听起来很聪明,我会试一试,让你知道我是怎么做的。 这太棒了,难怪你有157k! ;) 很好的答案!【参考方案2】:好的,这很容易,因为您使用的是 jQuery。 jQuery 带有一个集成的 Promise maker,它也与 jQuery 的 Ajax 调用相连。那是什么意思?好吧,我们可以这样轻松地进行:
var requests = [ ];
// ...
// Submit the ajax request
requests.push($.ajax(
type: 'POST',
url: 'ajax/url',
data:
name: name,
email: email
,
success: function(json)
// Log a console entry if our ajax request was successful
console.log(name + " was submitted via ajax");
));
// at this point we filled our array with jXHR objects which also inherit the promise API
$.when.apply( null, requests ).done(function()
document.location.href = '/thanks';
);
注意:上面的代码只有在所有请求都成功完成的情况下才会触发。如果您需要处理一个或多个请求失败的情况,也可以使用.then()
或.fail()
而不是.done()
。
【讨论】:
Felix 打败了你! :( +1 虽然。 确实,我做的“blabla”太多了:p 确实,这里没有第二名:p【参考方案3】:只需保留 AJAX 调用的计数器并检查它们何时全部完成。 像这样的:
$("#form").submit(function()
var ajaxMax = $(".friendName[value!='']").length, ajaxCounter = 0;
$(".friendName[value!='']").each(function()
var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName','');
if($("#"+idEmail+"[value!='']").length > 0)
var name = $(this).val();
var email = $("#"+idEmail).val();
// Submit the ajax request
$.ajax(
type: 'POST',
url: 'ajax/url',
data:
name: name,
email: email
,
success: function(json)
// Log a console entry if our ajax request was successful
console.log(name + " was submitted via ajax");
if(++ajaxCounter >= ajaxMax)
window.location= '/thanks';
);
);
);
【讨论】:
我刚刚意识到我发布的代码不能完全正常工作,因为你有一个“if”语句,所以在计算“max”时需要检查它。【参考方案4】:默认情况下 $.ajax 是异步的。在传递的选项哈希中,添加
async: false
这将序列化你正在进行的调用,让它按照你想要的方式执行。
在得到原发帖人的评论后,可能的解决办法是:
在提交调用中确定应该进行的调用次数。 将此结果存储为处理函数中的局部变量 在“完成:”上创建一个回调,它将检查调用的值 如果要调用的次数大于0,则递减该值并返回 如果调用次数为零,请更新 window.location(确实应该使用 window.location.href,因为 window.location 是一个对象,但浏览器会允许这样做并正确执行)注意,我没有关于执行这种操作的线程安全的任何信息,所以 YMMV。
示例代码:
$("#form").submit(function(eventObject)
var $ajaxFields= $(".friendName[value!='']").filter(function(index)
var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName','');
return ($("#"+idEmail+"[value!='']").length > 0);
);
var numberToSubmit= $ajaxFields.length;
$ajaxFields.each(function()
var idEmail = 'friendEmail' + $(this).attr("id").replace('friendName','');
var name = $(this).val();
var email = $("#"+idEmail).val();
// Submit the ajax request
$.ajax(
type: 'POST',
url: 'ajax/url',
data:
name: name,
email: email
,
success: function(json)
// Log a console entry if our ajax request was successful
console.log(name + " was submitted via ajax");
,
error: function(jqXHR, textStatus, errorThrown)
console.log("call not completed: "+textStatus);
,
complete: function(jqXHR, textStatus)
if( --numberToSubmit == 0 )
window.location.href= '/thanks';
);
);
// Prevent default form submission
return false;
);
【讨论】:
刚刚更新了我的问题,我尝试使用 async: false 但它似乎没有什么不同,我真的不希望浏览器在通话时冻结。 啊好吧...让我挖掘一下。 下面的评论使用延迟对象可能是更聪明的方法,不幸的是我没有任何使用它们的经验。以上是关于each() 函数中的多个 ajax 调用.. 然后在所有这些都完成后执行一些操作?的主要内容,如果未能解决你的问题,请参考以下文章
使用ajax jQuery for-each函数在表中追加多个数据