我正在使用嵌套的AJAX。我在所有AJAX调用之前禁用按钮,然后在最外面的AJAX中始终启用按钮。但是问题是我认为启用按钮的代码发生在最里面的AJAX的.done中的代码之前。是因为最外面的AJAX中的.always与最里面的AJAX中的.done并行运行吗?一个人先完成?
此问题的解决方法是什么?我是否需要使用Promise,以便在所有AJAX调用完成后启用按钮?如果是这样,您能告诉我如何?似乎很高级,我不理解我一直在阅读的代码。
function loginAndEnter() {
$("#login-and-enter-btn").prop('disabled', true);
$("#login-and-enter-btn").text('請稍等...');
$.ajax({ //Outermost AJAX
type:"GET",
url:"/qrcode/login/",
data:{
"cellphone":document.getElementById("cellphone").value,
"password":document.getElementById("password").value
}
})
.done(function(responsedata) {
var parsedJson = $.parseJSON(responsedata);
if(parsedJson.result==1){
document.getElementById("token").value = parsedJson.token;
$.ajax({
type:"GET",
url:"/qrcode/entry/",
data:{
"token":document.getElementById("token").value,
"parking_lot_id":{{ $parking_lot_id }},
"in_or_out":{{ $in_or_out }}
}
})
.done(function(responsedata) {
var parsedJson = $.parseJSON(responsedata);
if(parsedJson.result==1){
$.ajax({
type:"GET",
url:"/qrcode/zero/",
data:{
"booking_id":parsedJson.Booking_ID[0].id,
"token":document.getElementById("token").value
}
})
.done(function(responsedata) { //Innermost done
var parsedJson = $.parseJSON(responsedata);
if(parsedJson.result==1){
alert("進場成功! 請使用易停網APP繳費與出場.");
window.location.href = "/download";
}
else{
alert(parsedJson.title+"\n"+parsedJson.description);
}
})
.fail(function(xhr, status, errorThrown) {
...
});
}
else{
alert(parsedJson.title+"\n"+parsedJson.description);
}
})
.fail(function(xhr, status, errorThrown) {
...
});
}
else{
alert(parsedJson.title+"\n"+parsedJson.description);
}
})
.fail(function(xhr, status, errorThrown) {
...
})
.always(function() { //Outermost always
$("#login-and-enter-btn").prop('disabled', false);
$("#login-and-enter-btn").text('登入和升起柵欄進場');
});
}
答案 0 :(得分:1)
.always函数不会等待其他AJAX请求完成,因为它是在最外面的请求获得响应后立即调用的。嵌套请求的事实意味着后续的AJAX请求将在其他请求被解决后被调用,但是如果您只想在所有请求都被解决后再执行某些操作,则需要“承诺”。
我修改了您的代码,以显示通过Promises和async / await函数实现目标的一种方法。
function firstAJAX() {
return new Promise((resolve, reject) => {
$.ajax({ //Outermost AJAX
type:"GET",
url:"/qrcode/login/",
data:{
"cellphone": 111111111111,
"password": "pwd"
}
})
.done(function(responsedata) {
// var parsedJson = $.parseJSON(responsedata);
var parsedJson = {};
parsedJson.result = 1;
if(parsedJson.result==1){
resolve(responsedata);
}
else{
alert(parsedJson.title+"\n"+parsedJson.description);
}
})
.fail(function(xhr, status, errorThrown) {
console.log(status);
});
});
}
function secondAJAX(data) {
return new Promise((resolve, reject) => {
$.ajax({
type:"GET",
url:"/qrcode/entry/",
data:{
"token": "token",
"parking_lot_id": 11,
"in_or_out": 22
}
})
.done(function(responsedata) {
// var parsedJson = $.parseJSON(responsedata);
var parsedJson = {};
parsedJson.result = 1;
if(parsedJson.result==1){
resolve(responsedata);
}
else{
alert(parsedJson.title+"\n"+parsedJson.description);
}
})
.fail(function(xhr, status, errorThrown) {
console.log(status);
});
});
}
function thirdAJAX(data) {
return new Promise((resolve, reject) => {
$.ajax({
type:"GET",
url:"/qrcode/zero/",
data:{
"booking_id": 222,
"token":"token"
}
})
.done(function(responsedata) { //Innermost done
// var parsedJson = $.parseJSON(responsedata);
var parsedJson = {};
parsedJson.result = 1;
if(parsedJson.result==1){
alert("進場成功! 請使用易停網APP繳費與出場.");
// window.location.href = "/download";
resolve(responsedata);
}
else{
alert(parsedJson.title+"\n"+parsedJson.description);
}
})
.fail(function(xhr, status, errorThrown) {
console.log(status);
});
});
}
async function loginAndEnter() {
const first = await firstAJAX();
const second = await secondAJAX(first);
const third = await thirdAJAX(second);
$("#login-and-enter-btn").prop('disabled', false);
$("#login-and-enter-btn").text('登入和升起柵欄進場');
}
所以它的工作方式是loginAndEnter函数将等待firstAJAX,secondAJAX和thirdAJAX被解析。所有这些功能都返回Promises,当GET请求成功接收到响应时,将解决这些Promises。 secondAJAX和thirdAJAX接受一个参数,它是从之前调用的函数异步传递的响应(由于“ await”)。
我出于自己的测试目的更改了许多值,因此请在尝试之前将其更改回您的值。