我正在使用带有$.ajax
函数的jquery $.each
创建一个数组并推送AJAX查询。我希望在完成数组后页面应该刷新,但是当我尝试这样做时,页面之间会刷新。当我使用async:false
进行$.ajax
查询时,它工作正常,但这会导致性能下降(ajax查询完成所需的时间增加5倍)。有人可以给我指点如何去做,以下是我输入的代码:
$('#update1').click(function()
{
$.each(testarray,function(k,valu)
{
var count = testarray.length;
var checkloop = k+1;
var valkor = "/webresources/api/v3/sites/current/pages/" + valu.value;
var valkis = valu.checkbox;
var request =
$.ajax(
{
url: valkor,
processData: false,
data: JSON.stringify({ "enabled" : valkis }),
type: "PUT",
contentType: "application/json",
mimeType: "application/json ",
headers: { "Authorization": $.cookie('access_token') }
})
request.done(function(msg)
{
console.log("successfully updated");
})
request.fail(function(jqXHR)
{
console.log("Request failed.");
console.log("Error code: " + jqXHR.status);
console.log("Error text: " + jqXHR.statusText);
console.log("Response text: " + jqXHR.responseText);
})
request.then(function()
{
location.reload(true);
})
})
})
上面的代码刷新页面而不等待循环完成。我甚至试过循环。请让我知道我错过了什么。
答案 0 :(得分:2)
您可以使用jQuery .when
推迟操作,直到所有 AJAX请求完成后。
这样的事情:
function updateHandler()
{
var promisesArray = [];
var successCounter = 0;
var promise;
$.each(testarray, function(k, valu)
{
var count = testarray.length;
var checkloop = k+1;
var valkor = "/webresources/api/v3/sites/current/pages/" + valu.value;
var valkis = valu.checkbox;
promise =
$.ajax(
{
url: valkor,
processData: false,
data: JSON.stringify({ "enabled" : valkis }),
type: "PUT",
contentType: "application/json",
mimeType: "application/json ",
headers: { "Authorization": $.cookie('access_token') },
});
promise.done(function(msg)
{
console.log("successfully updated");
successCounter++;
});
promise.fail(function(jqXHR) { /* error out... */ });
promisesArray.push(promise);
});
$.when.apply($, promisesArray).done(function()
{
location.reload(true);
console.log("WAITED FOR " + successCounter + " OF " + testarray.length);
});
}
$('#update1').click(updateHandler);
请参阅$.when
的文档。
从jQuery 1.5开始,像$.ajax
这样的调用会返回 promise 。这些对于许多不同的事情都很有用(有关承诺的其他有用信息,请参阅this post),但在我们的案例中,我们希望收集承诺,以便为$.when
电话提供信息。推迟执行一段代码直到所有AJAX请求都返回响应。
在$.each
循环中,我们定义$.ajax
次调用。一旦定义了每个 - 在每次调用$.ajax
之后 - 通过网络发送请求,浏览器将等待响应。此外,我们还会为变量中的每个$.ajax
调用收集相关的承诺。在上面的代码中,我们对这些承诺中的每一个做了两件事:1)我们附加了单独的done
和error
函数来执行操作 - 特定于单个请求 - 每次通话结束后; 2)我们将承诺存储在promisesArray
中,以便我们只有在所有调用完成后才能采取行动。
这里需要注意的一点是,这一行:promise = $.ajax(...
不存储结果 - 即AJAX调用的响应 - 它存储与AJAX相关的承诺调用
最后,我们将这些承诺交给$.when
,done
使用它自己的testarray
函数来执行我们想要在所有AJAX调用返回后执行的操作。
上面的解决方案收集了一系列的承诺,因为我的问题假设和promisesArray
的使用是我们提前不知道需要多少次AJAX调用。如果确实知道你将使用多少个AJAX调用,我们可以从解决方案中删除$.when(
$.ajax( /* args for 1st call */ ).done( /* 1st call success code */ ),
$.ajax( /* args for 2nd call */ ).done( /* 2nd call success code */ ),
$.ajax( /* args for 3rd call */ ).done( /* 3rd call success code */ )
).done(function()
{
location.reload(true);
});
,在3个AJAX调用的情况下看起来像这样:
$.ajax
由于我们可能不知道需要多少次次来电,例如由于用户输入,我们需要收集与未知done
次呼叫相关的承诺。
在jQuery支持延迟执行之前 - 在jQuery 1.5之前 - 另一种处理问题的方法只有在这些其他N(通常是AJAX)操作完成之后才采取行动是保持一个大的状态变量:要完成N个动作,您将生成一组N个布尔值。当每个动作完成(返回一个AJAX调用)时,true
处理程序会做两件事:1)将它的标志设置为true
; 2)检查所有标志是否已设置为apply
,然后执行操作,例如重新加载页面。这是因为JavaScript事件队列处理的单线程特性。
此处还有一些事项需要注意:
$.when
,因为done
期望将延迟作为单独的参数。location.reload
调用上递增的计数器,如果你注释掉你应该看到的testarray
调用 - 假设PUT调用成功 - 那个值是计数器与$.when().done
。$.when().always()
与$.each
之间的区别来确定更适合您自己代码的内容。$.when
和click
循环的设置拉入单独的函数中。这是无关紧要的,您可以将它们保留在原始代码中的id
中,它仍然可以使用。valkor
并点击https://httpbin/put作为async: false;
网址进行了测试。一般不要使用{{1}} - 当你发现自己这样做总是备份并寻找另一种方式。 jQuery / JavaScript总是提供一个。
答案 1 :(得分:0)
从AJAX中取出'A'
因为async:false
通常是一个坏主意,因为它可能会导致各种各样的阻塞行为,这些行为可能会使您的体验变得非常糟糕,而对于某些请求,它甚至已被完全弃用:
从jQuery 1.8开始,使用async:false和jqXHR($ .Deferred) 弃用;您必须使用完整/成功/错误回调。
利用承诺
然而,jQuery支持使用when()
和then()
promise函数,它们允许您存储所有请求,异步执行它们,然后在完成所有请求后执行函数。
您只需将每个请求存储到一个数组中:
// Store your requests
var requestsToProcess = [];
// Build each request
$.each(testarray, function(k, valu){
// Push this request onto your array
requestsToProcess.push(
$.ajax({
url: "/webresources/api/v3/sites/current/pages/" + valu.value,
processData: false,
data: JSON.stringify({ "enabled" : valu.checkbox }),
type: "PUT",
contentType: "application/json",
mimeType: "application/json ",
headers: { "Authorization": $.cookie('access_token') },
done: function(msg){
console.log("successfully updated");
},
fail: function(jqXHR){
console.log("Request failed.");
console.log("Error code: " + jqXHR.status);
console.log("Error text: " + jqXHR.statusText);
console.log("Response text: " + jqXHR.responseText);
}
})
);
});
// Now that all of your arrays have been added, process them
$.when(requestsToProcess).then(function(){
// Everything has been processed, refresh
location.reload(true);
});