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

标签 javascript jquery ajax

我正在使用嵌套 AJAX。我在所有 AJAX 调用之前禁用按钮,然后在最外层 AJAX 中的 .always 中启用按钮。但问题是我认为启用按钮的代码发生在最里面 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('登入和升起柵欄進場');
        });
    }

最佳答案

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

我修改了您的代码,以展示使用 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被解析。所有这些函数都会返回 Promise,当 GET 请求成功收到响应时,这些 Promise 就会被解析。 SecondAJAX 和 ThirdAJAX 接受一个参数,该参数是从之前调用的函数异步传递的响应(感谢“await”)。

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

关于javascript - 第一个 AJAX 总是在最后一个嵌套 AJAX 完成之前发生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55862920/

相关文章:

javascript - 如何使用 React 库将数据导出到 Excel

javascript - MVC - 我的表单没有传递我的选择下拉列表的选定选项

java - 多个 ajax 数据到 Spring MVC Controller

javascript - Jquery IE 问题

第二次点击时执行的javascript函数

javascript - 了解闭包及其作用域

javascript - 如果使用 jquery/javascript 锁定 iphone,如何提交表单

javascript - 仅在焦点上显示输入中的最后 3 个字符?

javascript - 证券交易方计算

javascript - AJAX 未从 PHP 脚本返回预期输出