等到所有ajax请求完成

我需要等到我的所有ajaxfunction完成后再继续执行。

我的具体情况是我需要在提交之前翻译表单中的某些字段。 我用ajax调用外部网站来翻译它们。 根据表单中的某些值,我需要进行更多或更少的翻译。 完成所有翻译后(如果有的话)我必须用ajaxvalidation表单,如果有效,则提交。

这是我的方法:
首先,我有一个函数发送ajax调用并对收到的数据做一些事情:

function translate(...) { $("#ajaxCounter").val(parseInt($("#ajaxCounter").val()) + 1); $.ajax({ ... success:function(data) { ... $("#ajacCounter").val(parseInt($("#ajaxCounter").val()) - 1); } }); 

然后,当要提交表单时,我执行以下代码:

 $("#form").submit(function() { translatable_fields.each(function() { translate(...); }); while (parseInt($("#ajaxCounter").val()) > 0) { null; } if (!(this).hasClass('ready')) { $.ajax({ //validation success: function(data) { if (data['isValid']) { $("#form").addClass('ready'); $("#form").submit(); } } }); } return true; }); 

问题是提交函数中的while循环永远不会结束。

如果我在没有while循环的情况下执行代码while我可以看到ajaxCounter输入在转换函数开始时增加,在结束时减少。

您可以使用从$.ajax调用返回的deferred对象以更整洁的方式实现此目的。 首先你应该得到translate()函数来返回deferred

 function translate(...){ return $.ajax({ // settings... }); }); 

然后你可以把所有这些承诺放在一个数组中:

 var requests = []; translatable_fields.each(function(){ requests.push(translate(...)); }); 

然后你可以将该数组应用于$.when

 $.when.apply($, requests).done(function(schemas) { console.log("All requests complete"); // do something... }); 

您可以使用延迟对象执行此操作,但如果您只对最终完成感兴趣,则不需要将$.when.apply与数组一起使用。

相反,你可以使用模式promise = $.when(promise, another promise)链接并行承诺

更改您的翻译以返回Ajax承诺:

 function translate(...) { ... return $.ajax({ ... }); } 

而你的承诺循环变成:

 var promise; // Start with an undefined promise - which is the same as a resolved promise for $.when translatable_fields.each(function() { promise = $.when(promise, translate(...)); }); // Wait for all promises to complete promise.done(function(){ // now do the final code after all the ajax calls complete }); 

笔记:

  • 这确实为每次调用$.when创建了额外的承诺,但是开销非常小,结果代码非常简单。

不,你不能像这样循环:回调永远不会有机会被调用。

我会做这样的事情:

 function translateAllFields(done) { var requestsInProgress = 0, doneCalled = false; translatable_fields.each(function () { ++requestsInProgress; $.ajax({ //... success: function (data) { //... $("#ajacCounter").val(parseInt($("#ajaxCounter").val()) - 1); } }).always(function () { if (--requestsInProgress === 0) { done(); doneCalled = true; } }); }); if (requestsInProgress === 0 && !doneCalled) { // in case translatable_fields was empty done(); } } 

然后:

 $("#form").submit(function (e) { if (!(this).hasClass('ready')) { e.preventDefault(); e.stopPropagation(); translateAllFields(function() { $.ajax({ //validation success: function (data) { if (data['isValid']) { $("#form").addClass('ready'); $("#form").submit(); } } }); }); } }); 

你可以使用回调

 function translate(..., callback) { $.ajax({ ... success:function(data) { ... callback(data); } }); }; 

并将你的ajax代码传递给它

 $("#form").submit(function() { translatable_fields.each(function() { translate(..., function(result){ if (!(this).hasClass('ready')) { $.ajax({ //validation success: function(data) { if (data['isValid']) { $("#form").addClass('ready'); $("#form").submit(); } } }); } return true; }); }); });