我有一个使用ajax post方法和dataTables的程序。摆弄了几个星期之后,我确定我根本不明白javascript是如何工作的。 这是我的javascript:
$('#SaveTimeSheet').click(function () {
$("#TimeSheetLoader").removeClass("hidden");
GetSheetCount();
});
function GetSheetCount() {
$.ajax({
url: '@Url.Action("GetTimeSheetCount","TimeSheet",null)',
type: "POST",
data:{
OperatorId: $("#OperatorId option:selected").val()
},
success: function (Result) {
StartTimeSheet(Result.Result);
}
});
}
function StartTimeSheet(Result) {
$.ajax({
type: "POST",
url: '@Url.Action("Create", "TimeSheet", null)',
data: {
SpecificLocation: $("#SpecificLocation").val(),
DetailedPoint: $("#DetailedPoint").val(),
SheetStatus: $("#statusSlider").val(),
Description: $("#Description").val(),
OperatorHours: $("#OperatorHoursSlider").attr("data-value"),
OperatorMins: $("#OperatorMinsSlider").attr("data-value"),
AssistantHours: $("#AssistantHoursSlider").attr("data-value"),
AssistantMins: $("#AssistantMinsSlider").attr("data-value"),
OriginalQuote: $('input[name=OriginalQuote]:checked').val(),
QuoteNo: $("#QuoteNo").val(),
SINumber: $("#SINumber").val(),
OperatorId: $("#OperatorId option:selected").val(),
SiteName: $("#SiteId option:selected").text(),
Code: $("#SiteId option:selected").val() + "-" + $("#OperatorId option:selected").val() + "-" + (Result + 1) + "-" + today
},
success: function (Result) {
ProcessTable(Result.Result);
},
error: function (x, e) {
if (x.status == 0) {
alert('You are offline!!\n Please Check Your Network.');
} else if (x.status == 404) {
alert('Requested URL not found.');
} else if (x.status == 500) {
alert('Internel Server Error.');
} else if (e == 'parsererror') {
alert('Error.\nParsing JSON Request failed.');
} else if (e == 'timeout') {
alert('Request Time out.');
} else {
alert('Unknow Error.\n' + x.responseText);
}
}
});
}
function ProcessTable(Result) {
console.log("Start Table Process");
var datas = t.rows().data();
var total = $("#Table tr").length - 1;
var counter = 0;
for (var i = 0; i < total; i++) {
var value = datas[i];
AddItems(value, Result);
counter = counter + 1;
}
if (counter === total) {
SendPDF(Result);
}
}
function AddItems(value, Result) {
$.ajax({
type: "POST",
url: '@Url.Action("ProcessTable","TimeSheet",null)',
data: {
TimeSheetId:Result,
BOM_NO: value[0],
Stock_Code: value[1],
Stock_Description: value[2],
Quantity: value[3]
},
success: function (data) {
console.log(data.Result);
},
error: function () {
console.log("Error");
}
});
}
function SendPDF(Result) {
$.ajax({
type: "GET",
url: '/TimeSheet/SendTimeSheet?Id='+Result,
success: function (data) {
console.log(data.Result);
location.reload();
}
});
}
我遇到的麻烦是程序在ProcessTable函数中间执行SendPDF函数。我试图通过使用if语句来阻止它,但它仍然执行。
如果您知道如何修复我的代码,那太好了。但是如果你能解释javascript如何执行函数,以及按什么顺序执行。以及如何控制该订单。那会很棒。
答案 0 :(得分:1)
但是如果你能解释javascript如何执行函数,以及按什么顺序执行。以及如何控制该订单。那会很棒。
JavaScript函数的工作方式与大多数其他语言中的函数类似:当您调用函数时,它会运行完成,然后控制返回到您调用它的位置。 (在大多数JavaScript环境中,您甚至不必担心多个线程,因为虽然JavaScript不是单线程语言,但它使用的大多数环境每个全局只使用一个线程环境,让生活变得更加简单。)
代码中的问题是 asynchronicity 。在您的代码中,SendPDF
中间未调用ProcessResults
;在完成对AddItems
的所有调用并返回之后,它会在结束时被调用。 但是,当您致电AddItems
时,它所做的就是开始一个进程(ajax
请求),然后异步> ,与运行JavaScript的线程分开。因此SendPDF
在之前被称为所有这些ajax调用都有机会完成。
为了解决这个问题,我们等到那些ajax调用完成后让AddItems
返回$.ajax
给我们的承诺:
function AddItems(value, Result) {
// Return the Deferred that $.ajax gives us
return $.ajax({
type: "POST",
url: '@Url.Action("ProcessTable","TimeSheet",null)',
data: {
TimeSheetId: Result,
BOM_NO: value[0],
Stock_Code: value[1],
Stock_Description: value[2],
Quantity: value[3]
},
success: function(data) {
console.log(data.Result);
}/*, - Probably don't want this, instead we'll handle
errors in the calling code
error: function() {
console.log("Error");
}*/
});
}
...然后在ProcessResults
等待,直到所有这些承诺得到解决(稍后在ProcessResults
返回后发生):
function ProcessTable(Result) {
console.log("Start Table Process");
var datas = t.rows().data();
var total = $("#Table tr").length - 1;
// Remember the promises from AddItems in an array
var promises = [];
for (var i = 0; i < total; i++) {
var value = datas[i];
promises.push(AddItems(value, Result));
}
// Wait until they're all resolved...
$.when.apply($, promises).then(
function() {
// ...and then call SendPDF
SendPDF(Result);
},
function() {
// At least one of the ajax calls failed, handle it
}
);
}
$.when.apply($, someArray)
是我们需要的奇怪的符号,因为$.when
期望一个promises列表作为一系列参数而不是单个数组。所以我们必须使用Function#apply
来展开它们(在ES5及更早版本中;在ES2015及更高版本中,我们可以使用扩展符号)。
答案 1 :(得分:0)
首先,Javascript通常是单线程的;它在跳转到执行队列&#34;执行队列之前完全执行一个块。
现在,对于您的代码,您在 ProcessTable中调用SendPDF ,而在之后调用。如果希望SendPDF在ProcessTable之后执行,请在调用ProcessTable的行的正下方调用它。不同之处在于,如果执行此操作,则SendPDF将在ProcessTable返回后执行,这与当前代码所发生的情况不同。
每个Javascript开发人员需要注意的第二件事是从Javascript中出现的回调模式是单线程的。请注意,所有这些成功的ajax回调都不会在解析/解释的同时执行! Javascript引擎将立即继续执行下一行,并且回调可能仅在将来的某个时刻执行。如果您想更好地理解这一点,请在这些ajax调用之前以及成功回调中放置日志消息。