.each 函数完成后重新加载页面
Reload page after .each function completes
我正在创建一个数组并使用 jquery $.ajax
和 $.each
函数推送 AJAX 查询。我希望在数组完成后页面应该刷新,但是当我尝试这样做时页面会在两者之间刷新。当我对 $.ajax
查询使用 async:false
时,它工作正常,但这会导致性能下降(完成 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);
})
})
})
以上代码无需等待循环完成即可刷新页面。我什至尝试过循环。请让我知道我错过了什么。
您可以使用 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
return 一个 promise。这些对于许多不同的事情很有用(请参阅 this post 了解关于承诺的其他有用的事情),但在我们的例子中,我们希望收集承诺以提供给 $.when
调用,以便推迟一段代码的执行,直到所有 AJAX 请求 return 响应。
在$.each
循环中,我们定义了$.ajax
调用。一旦定义了每一个 - 在每次调用 $.ajax
之后 - 通过网络发送一个请求,浏览器将等待响应。此外,我们为变量中的每个 $.ajax
调用收集关联的 promise。在上面的代码中,我们对这些承诺中的每一个做了两件事:1)我们附加了单独的 done
和 error
函数来采取行动 - 特定于单独的请求 - 每次调用完成后; 2) 我们将承诺存储在 promisesArray
中,这样我们才能在 所有 调用完成后才采取行动。
这里要注意的重要一点是这一行:promise = $.ajax(...
不存储 result - 即 AJAX 调用的响应,它存储与 AJAX 调用关联的承诺。
最后,我们将这些承诺交给 $.when
,它使用它自己的 done
函数来执行我们想要在所有 AJAX 调用具有 return编辑
上面的解决方案收集了一系列承诺,因为我根据你的问题和你对 testarray
的使用做出的假设是我们无法提前知道需要多少次 AJAX 调用.如果您 确实 知道您将使用多少 AJAX 调用,我们可以从解决方案中删除 promisesArray
,在 3 [ 的情况下可能看起来像这样=107=] 调用:
$.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);
});
因为我们可能不知道需要多少次调用,例如由于用户输入,我们需要收集与未知数量的 $.ajax
调用相关的承诺。
在 jQuery 之前支持延迟执行 - 在 jQuery 1.5 之前 - 另一种处理问题的方法 仅在这些其他 N(通常是 AJAX) actions complete 是为了保持一个大的状态变量:要完成 N 个动作,你会产生一个 N 个布尔值数组。当每个动作完成时(AJAX 调用 returned),done
处理程序将做两件事:1)将其标志设置为 true
; 2) 检查是否所有 flags 都设置为true
,然后采取措施,例如重新加载页面。这是可行的,因为 JavaScript 事件队列处理的单线程性质。
这里还有几点需要注意:
- 你需要
apply
因为 $.when
需要 deferred 作为单独的参数。
- 我添加了一个计数器,该计数器在每次 AJAX
done
调用时递增,如果您注释掉 location.reload
调用,您应该会看到 - 假设 PUT 调用是成功 - 计数器的值匹配 testarray
. 的大小
- 您应该考虑使用
$.when().done
与 $.when().always()
之间的区别,以确定哪个更适合您自己的代码。
- 我已经将
$.each
和 $.when
循环的设置拉到一个单独的函数中。这是无关紧要的,您可以将它们保留在 click
中,就像在您的原始代码中一样,它仍然可以工作。
- 我通过添加一个按钮 update1 作为
id
并点击 https://httpbin/put 作为你的 valkor
[=125] 来测试这个=].
通常不要使用 async: false;
- 当您发现自己这样做时,请始终后退并寻找其他方法。 jQuery/JavaScript 总是提供一个。
从 AJAX
中取出 'A'
因为 async:false
通常不是一个好主意,因为它会导致各种阻塞行为,这些行为确实会扰乱您的体验,并且对于某些请求,它甚至已被完全弃用:
As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is
deprecated; you must use the complete/success/error callbacks.
利用承诺
jQuery 但是支持使用 when()
and 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);
});
我正在创建一个数组并使用 jquery $.ajax
和 $.each
函数推送 AJAX 查询。我希望在数组完成后页面应该刷新,但是当我尝试这样做时页面会在两者之间刷新。当我对 $.ajax
查询使用 async:false
时,它工作正常,但这会导致性能下降(完成 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);
})
})
})
以上代码无需等待循环完成即可刷新页面。我什至尝试过循环。请让我知道我错过了什么。
您可以使用 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
return 一个 promise。这些对于许多不同的事情很有用(请参阅 this post 了解关于承诺的其他有用的事情),但在我们的例子中,我们希望收集承诺以提供给 $.when
调用,以便推迟一段代码的执行,直到所有 AJAX 请求 return 响应。
在$.each
循环中,我们定义了$.ajax
调用。一旦定义了每一个 - 在每次调用 $.ajax
之后 - 通过网络发送一个请求,浏览器将等待响应。此外,我们为变量中的每个 $.ajax
调用收集关联的 promise。在上面的代码中,我们对这些承诺中的每一个做了两件事:1)我们附加了单独的 done
和 error
函数来采取行动 - 特定于单独的请求 - 每次调用完成后; 2) 我们将承诺存储在 promisesArray
中,这样我们才能在 所有 调用完成后才采取行动。
这里要注意的重要一点是这一行:promise = $.ajax(...
不存储 result - 即 AJAX 调用的响应,它存储与 AJAX 调用关联的承诺。
最后,我们将这些承诺交给 $.when
,它使用它自己的 done
函数来执行我们想要在所有 AJAX 调用具有 return编辑
上面的解决方案收集了一系列承诺,因为我根据你的问题和你对 testarray
的使用做出的假设是我们无法提前知道需要多少次 AJAX 调用.如果您 确实 知道您将使用多少 AJAX 调用,我们可以从解决方案中删除 promisesArray
,在 3 [ 的情况下可能看起来像这样=107=] 调用:
$.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);
});
因为我们可能不知道需要多少次调用,例如由于用户输入,我们需要收集与未知数量的 $.ajax
调用相关的承诺。
在 jQuery 之前支持延迟执行 - 在 jQuery 1.5 之前 - 另一种处理问题的方法 仅在这些其他 N(通常是 AJAX) actions complete 是为了保持一个大的状态变量:要完成 N 个动作,你会产生一个 N 个布尔值数组。当每个动作完成时(AJAX 调用 returned),done
处理程序将做两件事:1)将其标志设置为 true
; 2) 检查是否所有 flags 都设置为true
,然后采取措施,例如重新加载页面。这是可行的,因为 JavaScript 事件队列处理的单线程性质。
这里还有几点需要注意:
- 你需要
apply
因为$.when
需要 deferred 作为单独的参数。 - 我添加了一个计数器,该计数器在每次 AJAX
done
调用时递增,如果您注释掉location.reload
调用,您应该会看到 - 假设 PUT 调用是成功 - 计数器的值匹配testarray
. 的大小
- 您应该考虑使用
$.when().done
与$.when().always()
之间的区别,以确定哪个更适合您自己的代码。 - 我已经将
$.each
和$.when
循环的设置拉到一个单独的函数中。这是无关紧要的,您可以将它们保留在click
中,就像在您的原始代码中一样,它仍然可以工作。 - 我通过添加一个按钮 update1 作为
id
并点击 https://httpbin/put 作为你的valkor
[=125] 来测试这个=].
通常不要使用 async: false;
- 当您发现自己这样做时,请始终后退并寻找其他方法。 jQuery/JavaScript 总是提供一个。
从 AJAX
中取出 'A'因为 async:false
通常不是一个好主意,因为它会导致各种阻塞行为,这些行为确实会扰乱您的体验,并且对于某些请求,它甚至已被完全弃用:
As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the complete/success/error callbacks.
利用承诺
jQuery 但是支持使用 when()
and 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);
});