Javascript 第一个AJAX总是发生在最后一个嵌套AJAX完成之前

Javascript 第一个AJAX总是发生在最后一个嵌套AJAX完成之前,javascript,jquery,ajax,Javascript,Jquery,Ajax,我正在使用嵌套AJAX。我在所有AJAX调用之前禁用按钮,然后在内部启用按钮。始终在最外层的AJAX中。但问题是,我认为启用按钮的代码发生在最内部AJAX的.done中的代码之前。是因为.always in最外层的AJAX与.done in最内层的AJAX并行运行吗?一个比另一个先完成 解决这个问题的方法是什么?我是否需要使用承诺,以便在所有AJAX调用完成后启用按钮?如果是,你能告诉我怎么做吗?它似乎很先进,我不理解我一直在读的代码 function loginAndEnter() {

我正在使用嵌套AJAX。我在所有AJAX调用之前禁用按钮,然后在内部启用按钮。始终在最外层的AJAX中。但问题是,我认为启用按钮的代码发生在最内部AJAX的.done中的代码之前。是因为.always in最外层的AJAX与.done in最内层的AJAX并行运行吗?一个比另一个先完成

解决这个问题的方法是什么?我是否需要使用承诺,以便在所有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('登入和升起柵欄進場');
        });
    }

.always函数不会等待其他AJAX请求完成,因为它是在最外层的请求得到响应后立即调用的。请求是嵌套的,这意味着后续的AJAX请求将在其他请求被解析后被调用,但是如果您只想在所有请求都被解析后才执行某些操作,那么就需要承诺

我修改了您的代码,以显示通过承诺和异步/等待函数实现目标的一种方法

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('登入和升起柵欄進場');
}
因此,它的工作方式是loginandtenter函数将等待firstAJAX、secondAJAX和thirdAJAX被解析。所有这些函数都返回承诺,当GET请求成功接收到响应时,这些承诺将得到解决。secondAJAX和thirdAJAX接受一个参数,这是从之前调用的函数异步传递的响应(由于“wait”)


我为了自己的测试目的更改了许多值,所以请在尝试之前将它们更改回您的值

谈论地狱。。我建议对这个区块进行彻底检修,防止如此多的嵌套。从长远来看,你会感谢我的。我本人拒绝帮助您修复此代码,因为老实说,您将来可能会遇到更多问题