我有一些javascript代码使用http处理程序将一些数据更新到数据库,但是此异步调用是在.each
循环内进行的。在循环结束时,我调用了刷新页面的函数CancelChanges()
。问题是在更新数据库之前页面似乎刷新了。调用.each
后,CancelChanges()
循环似乎已完成。在.each循环中完成所有异步调用后,如何确保刷新页面?
function SaveChanges() {
if (PreSaveValidation()) {
var allChangesSucceeded = true;
var studioId = $("#param_studio_id").val();
var baseDate = $("#param_selected_month").val().substring(6, 10) + $("#param_selected_month").val().substring(0,2);
var currency = "CAD";
var vacationPct = null;
var gvAdmissible = null;
$(".editable-unsaved").each( function() {
var newSalary = $(this).text();
var disciplineId = $(this).data("disciplineid");
var seniorityId = $(this).data("seniorityid");
var handlerCommand = "";
if ($(this).data("valuetype") === "inflated") {
handlerCommand = "AddAverageSalary";
} else if ($(this).data("valuetype") === "actual") {
handlerCommand = "UpdateAverageSalary";
}
$.get("WS/AverageSalary.ashx", { command: handlerCommand, studio_id: studioId, discipline_id: disciplineId, seniority_id: seniorityId, base_date: baseDate, currency: currency, salary: newSalary, vacation_pct: vacationPct, gv_admissible: gvAdmissible }).done(function (data) {
if (data != "1") {
$(this).removeClass("editable-unsaved");
allChangesSucceeded = true;
}
else {
alert('fail');
allChangesSucceeded = false;
}
});
});
if(allChangesSucceeded) CancelChanges();
}
}
function CancelChanges() {
var href = window.location.href;
href = href.split('#')[0];
window.location.href = href;
}
答案 0 :(得分:6)
您可以尝试使用Promises和jQuery $.when
存储ajax调用promises的列表:
var defereds = [];
$(".editable-unsaved").each( function() {
//...
defereds.push($.get("WS/AverageSalary.ashx" /*...*/));
}
$.when.apply($, defereds).done(function() {
CancelChanges();
});
希望等待所有ajax调用完成后再调用CancelChanges()
答案 1 :(得分:2)
我认为您需要稍微更改一下结构,使用计数器并在计数器等于调用次数时调用CancelChanges。
function SaveChanges() {
if (PreSaveValidation()) {
var studioId = $("#param_studio_id").val();
var baseDate = $("#param_selected_month").val().substring(6, 10) + $("#param_selected_month").val().substring(0,2);
var currency = "CAD";
var vacationPct = null;
var gvAdmissible = null;
var editableUnsaveds = $(".editable-unsaved"); //cache the selector here, because selectors are costly
var numOfGetsReturned = 0;
editableUnsaveds.each( function() {
var newSalary = $(this).text();
var disciplineId = $(this).data("disciplineid");
var seniorityId = $(this).data("seniorityid");
var handlerCommand = "";
if ($(this).data("valuetype") === "inflated") {
handlerCommand = "AddAverageSalary";
} else if ($(this).data("valuetype") === "actual") {
handlerCommand = "UpdateAverageSalary";
}
$.get("WS/AverageSalary.ashx", { command: handlerCommand, studio_id: studioId, discipline_id: disciplineId, seniority_id: seniorityId, base_date: baseDate, currency: currency, salary: newSalary, vacation_pct: vacationPct, gv_admissible: gvAdmissible }).done(function (data) {
if (data != "1") {
$(this).removeClass("editable-unsaved");
}
else {
alert('fail');
}
if(editableUnsaveds.length === ++numOfGetsReturned){
CancelChanges(); //now it should call when the final get call finishes.
}
});
});
}
}
function CancelChanges() {
var href = window.location.href;
href = href.split('#')[0];
window.location.href = href;
}
答案 2 :(得分:1)
我使用promises。 q library是我最喜欢的实现方法。但是,既然您正在使用JQuery,我建议您按照与我在下面概述的方法类似的方法,但使用$.when
,而不是q.allSettled
我经常在同时抓取大量网站时使用承诺 - 我需要遍历一长串网站,发出内容请求,并在请求返回时对内容执行某些操作。我要做的最后一件事是一次发送一个请求,在返回时处理每个请求。
在摘要中,看起来像这样:
function scrapeFromMany() {
var promises = [];
_.forEach(urls, function(url) {
// this makes the request
var promise = scraper(url);
// this stores the promise with the others you iterate through
promises.push(promise);
});
q.allSettled(promises).then(function(res) {
// this function is executed when all of the promises (requests) have been resolved
console.log("Everything is done -- do something with the results.", res);
});
}
Fwiw,如果你从未使用它们,那么承诺并不容易。如果是这种情况,请计划花一些时间来熟悉这些概念。它们会改变(为了更好)你编写异步javascript的方式,而且它们确实是这些操作的有福路径。
答案 3 :(得分:0)
在"完成"内异步调用您的支票功能。函数处理程序跟踪已完成的请求数量,并且仅在预期请求总数等于您的处理时进行处理。
if (PreSaveValidation()) {
var allChangesSucceeded = true;
var length = $(".editable-unsaved").length;
var completedCount = 0;
// ...
$(".editable-unsaved").each( function() {
// ...
$.get("WS/AverageSalary.ashx", data).done(function (data) {
completedCount++;
if (data != "1") {
$(this).removeClass("editable-unsaved");
// don't set all changes succeeded to true here
}
else {
alert('fail');
allChangesSucceeded = false;
}
isComplete(length, completedCount, allChangesSucceeded);
});
});
}
function isComplete(totalLength, currentLength, allChangesSucceeded) {
if (currentLength == totalLength) {
// should this be !allChangesSucceeded?
if (allChangesSucceeded) CancelChanges();
}
}
答案 4 :(得分:0)
这是因为您没有等待请求完成以继续循环。 要实现这一点,您必须将“async”标志设置为false。 对服务器的调用应该是这样的:
$.ajax({ url: "WS/AverageSalary.ashx", async: false, data:{ command: handlerCommand, studio_id: studioId, discipline_id: disciplineId, seniority_id: seniorityId, base_date: baseDate, currency: currency, salary: newSalary, vacation_pct: vacationPct, gv_admissible: gvAdmissible }, success: function (data) { if (data != "1") { $(this).removeClass("editable-unsaved"); allChangesSucceeded = true; } else { alert('fail'); allChangesSucceeded = false; } } });