等到所有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; }); }); });