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

时间:2019-04-26 07:38:15

标签: javascript jquery ajax

我正在使用嵌套的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('登入和升起柵欄進場');
        });
    }

1 个答案:

答案 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”)。

我出于自己的测试目的更改了许多值,因此请在尝试之前将其更改回您的值。