我遇到了由异步Javascript执行引起的问题。我尝试使用函数设置变量的值,然后在函数调用后立即使用该变量。我想实现JQuery .when和.then来解决此问题,但是我在如何实现.then知道何时开始执行所需的承诺方面遇到了麻烦。
这是我所拥有的:
function addSerialNumber(item_id) {
var serialNumberList;
var serialNumber = $("serial-number").val();
$.when(serialNumberList = addSerialFunc(item_id, serialNumber))
.then(alert("Serial number successfully added."),
insertTransaction(item_id, serialNumberList));
}
function addSerialFunc(item_id, serialNumber) {
var serialNumberList = new Array();
$.ajax({
type: "post",
url: "someRandom.jsp",
data: {wsFunction: "Insert", item_id: item_id, serialNumber: serialNumber},
async: false
}).done(function(xml){
$(xml).find("Item").each(function() {
insert_id = ($(this).find("SendBack_CD").text());
if (!runError(insert_id, item_id)) {
//Fail
} else {
//Success
serialNumberList.push(insert_id);
}
})
}).fail(function(jqXHR, textStatus, errorThrown) {
console.log("Error occured! Type: " + textStatus + " HTTP Error Thrown: " + errorThrown);
});
return serialNumberList;
}
我试图通过调用addSerialFunc()创建serialNumberList,然后将serialNumberList用作insertTransaction()的参数。有时候可以用,但是我间歇性地得到
Uncaught TypeError: Cannot read property 'substring' of undefined
因为它试图在由addSerialFunc()填充serialNumberList之前执行insertTransaction()。
如何在addSerialFunc()中实现诺言,以便.then知道何时开始执行?
答案 0 :(得分:1)
几个问题:
在addSerialFunc
中,您将同步返回一个值,但是只有在异步ajax调用返回响应时,才会稍后填充该值。相反,您应该返回由$.ajax
返回的承诺 。
您立即调用alert
,而不是将回调函数传递给then
。
您将第二个参数传递给then
,由于与上一点相同的原因,该参数也不是函数。但是,第二个参数应该是承诺何时被拒绝的函数。
因此,这应该更好用-假定使用jQuery 3.x版:
function addSerialNumber(item_id) {
var serialNumberList;
var serialNumber = $("serial-number").val();
// *** $.when is not needed
addSerialFunc(item_id, serialNumber) // *** start with the returned promise
.then(function (serialNumberList) { // pass a function(!), which gets the value as argument
alert("Serial number successfully added.");
insertTransaction(item_id, serialNumberList);
}).catch(function (err) { // better to also have a `catch` call here
console.log(err);
console.log("because of error, no transaction is inserted");
});
}
function addSerialFunc(item_id, serialNumber) {
return $.ajax({
// ^^^^^^
type: "post",
url: "someRandom.jsp",
data: {wsFunction: "Insert", item_id: item_id, serialNumber: serialNumber}
/* drop the `async` property */
}).then(function(xml){
// ^^^^
var serialNumberList = new Array(); // *** define here
$(xml).find("Item").each(function() {
var insert_id = ($(this).find("SendBack_CD").text());
// ^^^^ make sure to always define the scope of your variables!
if (!runError(insert_id, item_id)) {
//Fail
throw "Some error occurred"; // *** adapt message here
^^^^^^
} else {
//Success
serialNumberList.push(insert_id);
}
});
return serialNumberList; // *** return!!!!
}).catch(function(jqXHR, textStatus, errorThrown) {
// ^^^^^
console.log("Error occured! Type: " + textStatus + " HTTP Error Thrown: " + errorThrown);
throw errorThrown; // *** cascade the error
});
}