【问题标题】:Wait until all jQuery Ajax requests are done?等到所有 jQuery Ajax 请求都完成?
【发布时间】:2020-03-17 04:00:35
【问题描述】:

如何让一个函数等到所有 jQuery Ajax 请求都在另一个函数中完成?

简而言之,在执行下一个请求之前,我需要等待所有 Ajax 请求完成。但是怎么做呢?

【问题讨论】:

  • 你如何调用你原来的 ajax 请求?
  • “完成”是什么意思?我将其理解为“所有请求都已成功完成或未完成”(已解决或被拒绝)。但是您可能的意思是“所有请求都已成功完成”(已解决)。查看api.jquery.com/category/deferred-object中的所有变体

标签: javascript jquery ajax


【解决方案1】:

jQuery 现在为此定义了一个when function

它接受任意数量的 Deferred 对象作为参数,并在它们全部解析时执行一个函数。

这意味着,如果你想发起(例如)四个 ajax 请求,然后在它们完成后执行一个操作,你可以这样做:

$.when(ajax1(), ajax2(), ajax3(), ajax4()).done(function(a1, a2, a3, a4){
    // the code here will be executed when all four ajax requests resolve.
    // a1, a2, a3 and a4 are lists of length 3 containing the response text,
    // status, and jqXHR object for each of the four ajax calls respectively.
});

function ajax1() {
    // NOTE:  This function must return the value 
    //        from calling the $.ajax() method.
    return $.ajax({
        url: "someUrl",
        dataType: "json",
        data:  yourJsonData,            
        ...
    });
}

在我看来,它的语法简洁明了,并且避免了涉及任何全局变量,例如 ajaxStart 和 ajaxStop,这可能会在您的页面开发过程中产生不必要的副作用。

如果您事先不知道需要等待多少个 ajax 参数(即您想使用可变数量的参数),它仍然可以完成,但有点棘手。见Pass in an array of Deferreds to $.when()(也许还有jQuery .when troubleshooting with variable number of arguments)。

如果您需要更深入地控制 ajax 脚本等的故障模式,您可以保存 .when() 返回的对象 - 这是一个包含所有原始 ajax 查询的 jQuery Promise 对象。您可以在其上调用.then().fail() 以添加详细的成功/失败处理程序。

【讨论】:

  • 这应该被标记为正确答案,因为它简单、高效且效果​​很好。另外需要注意的是,$.when 返回一个Promise 对象,它有更多有用的方法,而不仅仅是.done。例如,使用.then(onSuccess, onFailure) 方法,您可以在两个请求都成功或其中至少一个失败时做出反应。
  • 是否可以将请求 ajax1..4 打包成一个数组并传递?
  • 小心fail 的情况。与done 不同,fail 在第一次失败时立即触发并忽略剩余的延迟。
  • @skalee 感谢您强调可以附加 onFailure 函数这一事实。正如我在对 OP 问题的评论中指出的那样:他可能想更准确地指出他所说的“完成”是什么意思。关于faildone 的行为不同,“Ryan Mohr”也确实有一个很好的观点,关于Promises 的一些进一步阅读我猜html5rocks.com/en/tutorials/es6/promises
  • 让人们接触 when 方法和一般的 Promise 很棒,但我认为这不是最好的答案。如果任何这些 ajax 函数在任何地方创建另一个 ajax 请求,然后不正确地将新的承诺集成到链中......这些请求将逃避这种技术。例如,如果不修改我用于 ajax 添加到购物车行为的 Shopify 库,我就无法使用此技术,因为它不是以“承诺”的方式编写的,并且永远不会返回它创建的 xhr 对象。这有意义吗?不过,这仍然是一个很好的答案!
【解决方案2】:

如果你想知道什么时候ajax请求在你的文档中完成,不管它们有多少,只需这样使用$.ajaxStop事件:

$(document).ajaxStop(function () {
  // 0 === $.active
});

在这种情况下,您既不需要猜测应用程序中发生了多少请求,这些请求可能会在将来完成,也不需要深入研究函数的复杂逻辑或查找哪些函数正在执行HTTP(S) 请求。

$.ajaxStop 这里也可以绑定到任何你指定的HTML 节点 think 可能会被请求修改。


更新:
如果你想坚持使用ES 语法,那么你可以使用Promise.all 已知的ajax 方法:

Promise.all([ajax1(), ajax2()]).then(() => {
  // all requests finished successfully
}).catch(() => {
  // all requests finished but one or more failed
})

这里有趣的一点是它适用于 Promises$.ajax 请求。

这里是jsFiddle 演示。


更新 2:
使用async/await 语法的更新版本:

try {
  const results = await Promise.all([ajax1(), ajax2()])
  // do other actions
} catch(ex) { }

【讨论】:

  • +1 比其他答案要好得多如果您必须使用匿名回调/关闭来处理 3rd 方脚本。
  • @kaiser 有效点,但这不是问题所在。如果您不想等待所有 AJAX 调用返回,那就不是很好了。这个问题是关于等待您自己进行的 AJAX 调用的具体问题(如 OP 所写,在另一个函数中调用)。其他一些代码可能已经进行了另一个您不想等待的 AJAX 调用。
  • 相比when()方案,它的优势在于即使ajax调用次数未知也能正常工作。
  • 与 when() 解决方案相比,它的一个很大的缺点是不能与其他组件很好地协同工作,因为它共享一个文档范围的全局状态。如果持续进行长时间的轮询,它甚至可能永远不会触发。
  • 你不正确@AdrienBe,ajaxStop 处理所有 ajax 请求,无论它们成功与否,就像我的话证明看这个jsfiddle.net/36votxba/2
【解决方案3】:

我通过gnarf 找到了我自己的good answer,这正是我要找的:)

jQuery ajaxQueue

//This handles the queues    
(function($) {

  var ajaxQueue = $({});

  $.ajaxQueue = function(ajaxOpts) {

    var oldComplete = ajaxOpts.complete;

    ajaxQueue.queue(function(next) {

      ajaxOpts.complete = function() {
        if (oldComplete) oldComplete.apply(this, arguments);

        next();
      };

      $.ajax(ajaxOpts);
    });
  };

})(jQuery);

然后你可以像这样向队列中添加一个ajax请求:

$.ajaxQueue({
        url: 'page.php',
        data: {id: 1},
        type: 'POST',
        success: function(data) {
            $('#status').html(data);
        }
    });

【讨论】:

  • 你好像忘记给this answer提供正确的归属,我已经添加了。
【解决方案4】:

使用ajaxStop 事件。

例如,假设您在获取 100 个 ajax 请求时有一个 正在加载 ... 消息,并且您希望在加载后隐藏该消息。

来自 jQuery doc:

$("#loading").ajaxStop(function() {
  $(this).hide();
});

请注意,它将等待该页面上完成的所有 ajax 请求。

【讨论】:

  • 这假设您知道页面上不会有任何其他 AJAX 请求,这不是一个很好的假设
  • 从 jQuery 1.8 开始,.ajaxStop() 方法只能附加到文档。
  • 如果我错了,请纠正我,但这不会把你的项目变成一个“老派网络表单”网站吗?我的意思是,如果您的整个页面必须等待请求才能继续,那么首先 ajax 请求的意义何在?
  • @BillRuhl 在我们的例子中,我正在循环一个 jquery 集合来构建新的东西,并且在完成一些布局调整之前需要了解整个集合。似乎不是一个特别不寻常的案例。如果一堆其他 ajax 的东西可能正在处理中,那就太糟糕了,但这里不会。
【解决方案5】:

注意:上述答案使用了在编写此答案时不存在的功能。我建议使用jQuery.when() 而不是这些方法,但出于历史目的,我会留下答案。

-

您可能会使用一个简单的计数信号量,尽管您如何实现它取决于您的代码。一个简单的例子是......

var semaphore  = 0,     // counting semaphore for ajax requests
    all_queued = false; // bool indicator to account for instances where the first request might finish before the second even starts

semaphore++;
$.get('ajax/test1.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test2.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test3.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test4.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

// now that all ajax requests are queued up, switch the bool to indicate it
all_queued = true;

如果您希望它像 {async: false} 一样运行,但又不想锁定浏览器,您可以使用 jQuery 队列完成同样的事情。

var $queue = $("<div/>");
$queue.queue(function(){
    $.get('ajax/test1.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test2.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test3.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test4.html', function(data) {
        $queue.dequeue();
    });
});

【讨论】:

  • 这似乎会使一个琐碎的问题过于复杂。
  • 其实没那么复杂。计数信号量是 CS 中的一种常见机制。不过,如果您愿意,使用 jQuery 队列的示例也可以正常工作,而无需自己实现信号量。
  • 我没有看到信号量计数器有问题,但是,我确实看到了使用四个函数来处理结果回调的想法的问题。您应该先定义一个函数,然后在每个.get() 中引用该函数。这样至少您不会复制该代码。不仅如此,每次声明function(){} 都会分配内存!如果您可以调用静态定义的函数,那将是相当糟糕的做法。
  • @AlexisWilke 这是一个已有 4.5 年历史的答案,它旨在作为信号量和队列如何工作的示例。你想得有点过头了,我认为没有必要用大写来表达观点。
  • 嗯......我不是给你-1的人......而且我知道答案确实会老化。然而,人们一直在寻找它们,据我所知,向今天仍有可能使用它们的人提供信息是不被禁止的。
【解决方案6】:

一个小解决方法是这样的:

// Define how many Ajax calls must be done
var ajaxCalls = 3;
var counter = 0;
var ajaxCallComplete = function() {
    counter++;
    if( counter >= ajaxCalls ) {
            // When all ajax calls has been done
        // Do something like hide waiting images, or any else function call
        $('*').css('cursor', 'auto');
    }
};

var loadPersons = function() {
        // Show waiting image, or something else
    $('*').css('cursor', 'wait');

    var url = global.ctx + '/loadPersons';
    $.getJSON(url, function(data) {
            // Fun things
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCountries = function() {
    // Do things
    var url = global.ctx + '/loadCountries';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCities = function() {
    // Do things
    var url = global.ctx + '/loadCities';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

$(document).ready(function(){
    loadPersons();
    loadCountries();
    loadCities();
});

希望有用...

【讨论】:

  • 虽然其他答案在技术上更好,因为它更容易理解,但我真的很喜欢这个。不错!
【解决方案7】:

javascript 是基于事件的,所以你不应该等待,而应该设置钩子/回调

您可能只使用jquery.ajax 的成功/完成方法

或者你可以使用.ajaxComplete

$('.log').ajaxComplete(function(e, xhr, settings) {
  if (settings.url == 'ajax/test.html') {
    $(this).text('Triggered ajaxComplete handler.');
    //and you can do whatever other processing here, including calling another function...
  }
});

虽然你应该发布一个伪代码,说明你的 ajax 请求是如何被调用的,以便更精确......

【讨论】:

    【解决方案8】:

    jQuery 允许您指定是否希望 ajax 请求是异步的。您可以简单地使 ajax 请求同步,然后其余代码在它们返回之前不会执行。

    例如:

    jQuery.ajax({ 
        async: false,
        //code
    });
    

    【讨论】:

    • 需要注意的是,使用 { async: false } 可以暂时锁定浏览器。 api.jquery.com/jQuery.ajax
    • 这与标准的 jQuery/Javascript 实践背道而驰。 AJAX 总是应该是异步的。您应该改用 jQuery.when()。
    • 这是个非常糟糕的主意! 永远不要那样做!阻塞 = 根本不响应用户操作,甚至不响应滚动或任何操作! (另外,async: false 将在 jQuery 1.8 中被弃用。)
    • 特别是如果请求失败或由于某些不可预知的原因需要很长时间(根据墨菲定律,这必然会发生!),由于浏览器锁定,这对于生产代码通常是一个坏主意如上所述。
    • 这是一个非常糟糕的主意。不要使用这个答案。
    【解决方案9】:

    正如提到的其他答案,您可以使用 ajaxStop() 等待所有 ajax 请求完成。

    $(document).ajaxStop(function() {
         // This function will be triggered every time any ajax request is requested and completed
    });
    

    如果您想针对特定的ajax() 请求执行此操作,最好在特定的 ajax 请求中使用 complete() 方法:

    $.ajax({
        type: "POST",
        url: "someUrl",
        success: function(data) {
            // This function will be triggered when ajax returns a 200 status code (success)
        },
        complete: function() {
            // This function will be triggered always, when ajax request is completed, even it fails/returns other status code
        },
        error: function() {
            // This will be triggered when ajax request fail.
        }
    });
    


    但是,如果您只需要等待几个特定的​​ ajax 请求完成? 使用美妙的 javascript promises 等到您想要等待的这些 ajax 完成完毕。我制作了一个简短易读的示例,向您展示 Promise 如何与 ajax 一起使用。
    请看下一个示例。我用setTimeout 来说明这个例子。

    // Note:
    // resolve() is used to mark the promise as resolved
    // reject() is used to mark the promise as rejected
    
    $(document).ready(function() {
        $("button").on("click", function() {
    
            var ajax1 = new Promise((resolve, reject) => {
                $.ajax({
                    type: "GET",
                    url: "https://miro.medium.com/max/1200/0*UEtwA2ask7vQYW06.png",
                    xhrFields: { responseType: 'blob'},
                    success: function(data) {
                        setTimeout(function() {
                            $('#image1').attr("src", window.URL.createObjectURL(data));
                            resolve(" Promise ajax1 resolved");
                        }, 1000);
                    },
                    error: function() {
                        reject(" Promise ajax1 rejected");
                    },
                });
            });
    
            var ajax2 = new Promise((resolve, reject) => {
                $.ajax({
                    type: "GET",
                    url: "https://cdn1.iconfinder.com/data/icons/social-media-vol-1-1/24/_github-512.png",
                    xhrFields: { responseType: 'blob' },
                    success: function(data) {
                        setTimeout(function() {
                             $('#image2').attr("src", window.URL.createObjectURL(data));
                             resolve(" Promise ajax2 resolved");
                        }, 1500);
                    },
                    error: function() {
                        reject(" Promise ajax2 rejected");
                    },
                });
            });
    
            var ajax3 = new Promise((resolve, reject) => {
                $.ajax({
                    type: "GET",
                    url: "https://miro.medium.com/max/632/1*LUfpOf7teWvPdIPTBmYciA.png",
                    xhrFields: { responseType: 'blob' },
                    success: function(data) {
                        setTimeout(function() {
                             $('#image3').attr("src", window.URL.createObjectURL(data));
                             resolve(" Promise ajax3 resolved");
                        }, 2000);
                    },
                    error: function() {
                        reject(" Promise ajax3 rejected");
                    },
                });
            });
            
            Promise.all([ajax1, ajax2, ajax3]).then(values => {
                console.log("We waited until ajax ended: " + values);
                console.log("My few ajax ended, lets do some things!!")
            }, reason => {
                console.log("Promises failed: " + reason);
            });
            
            // Or if you want wait for them individually do it like this
            // ajax1.then(values => {
            //    console.log("Promise 1 resolved: " + values)
            // }, reason => {
            //     console.log("Promise 1 failed: " + reason)
            // });
        });
    
    });
    img {
      max-width: 200px;
      max-height: 100px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <button>Make AJAX request</button>
    <div id="newContent">
        <img id="image1" src="">
        <img id="image2" src="">
        <img id="image3" src="">
    </div>

    【讨论】:

      【解决方案10】:

      如果你需要一些简单的东西;一次完成回调

              //multiple ajax calls above
              var callback = function () {
                  if ($.active !== 0) {
                      setTimeout(callback, '500');
                      return;
                  }
                  //whatever you need to do here
                  //...
              };
              callback();
      

      【讨论】:

      • 它可以产生无限循环!
      • 这是一个死循环?什么时候?当 AJAX 永远不会返回?
      【解决方案11】:

      你也可以使用async.js

      我认为它比 $.when 更好,因为您可以合并各种不支持开箱即用承诺的异步调用,例如超时、SqlLite 调用等,而不仅仅是 ajax 请求。

      【讨论】:

        【解决方案12】:

        在@BBonifield 回答的基础上,我写了一个实用函数,这样信号量逻辑就不会散布在所有的ajax 调用中。

        untilAjax 是一个实用函数,它在所有 ajaxCall 完成时调用回调函数。

        ajaxObjs是一个ajax设置对象数组[http://api.jquery.com/jQuery.ajax/]

        fn是回调函数

        function untilAjax(ajaxObjs, fn) {
          if (!ajaxObjs || !fn) {
            return;
          }
          var ajaxCount = ajaxObjs.length,
            succ = null;
        
          for (var i = 0; i < ajaxObjs.length; i++) { //append logic to invoke callback function once all the ajax calls are completed, in success handler.
            succ = ajaxObjs[i]['success'];
            ajaxObjs[i]['success'] = function(data) { //modified success handler
              if (succ) {
                succ(data);
              }
              ajaxCount--;
              if (ajaxCount == 0) {
                fn(); //modify statement suitably if you want 'this' keyword to refer to another object
              }
            };
            $.ajax(ajaxObjs[i]); //make ajax call
            succ = null;
          };
        

        示例:doSomething 函数使用 untilAjax

        function doSomething() {
          // variable declarations
          untilAjax([{
            url: 'url2',
            dataType: 'json',
            success: function(data) {
              //do something with success data
            }
          }, {
            url: 'url1',
            dataType: 'json',
            success: function(data) {
              //do something with success data
            }
          }, {
            url: 'url2',
            dataType: 'json',
            success: function(response) {
              //do something with success data
            }
          }], function() {
            // logic after all the calls are completed.
          });
        }
        

        【讨论】:

          【解决方案13】:

          如果您是从头开始,我强烈建议您使用$.when()

          即使这个问题有超过一百万个答案,我仍然没有找到任何对我的案例有用的东西。假设您必须处理现有的代码库,已经进行了一些 ajax 调用,并且不想引入承诺的复杂性和/或重做整个事情。

          我们可以轻松利用 jQuery .data.on.trigger 函数,这些函数自古以来就是 jQuery 的一部分。

          Codepen

          我的解决方案的优点是:

          • 很明显回调到底取决于什么

          • 函数triggerNowOrOnLoaded不关心数据是否已经加载或者我们还在等待它

          • 将其插入现有代码非常容易

          $(function() {
          
            // wait for posts to be loaded
            triggerNowOrOnLoaded("posts", function() {
              var $body = $("body");
              var posts = $body.data("posts");
          
              $body.append("<div>Posts: " + posts.length + "</div>");
            });
          
          
            // some ajax requests
            $.getJSON("https://jsonplaceholder.typicode.com/posts", function(data) {
              $("body").data("posts", data).trigger("posts");
            });
          
            // doesn't matter if the `triggerNowOrOnLoaded` is called after or before the actual requests 
            $.getJSON("https://jsonplaceholder.typicode.com/users", function(data) {
              $("body").data("users", data).trigger("users");
            });
          
          
            // wait for both types
            triggerNowOrOnLoaded(["posts", "users"], function() {
              var $body = $("body");
              var posts = $body.data("posts");
              var users = $body.data("users");
          
              $body.append("<div>Posts: " + posts.length + " and Users: " + users.length + "</div>");
            });
          
            // works even if everything has already loaded!
            setTimeout(function() {
          
              // triggers immediately since users have been already loaded
              triggerNowOrOnLoaded("users", function() {
                var $body = $("body");
                var users = $body.data("users");
          
                $body.append("<div>Delayed Users: " + users.length + "</div>");
              });
          
            }, 2000); // 2 seconds
          
          });
          
          // helper function
          function triggerNowOrOnLoaded(types, callback) {
            types = $.isArray(types) ? types : [types];
          
            var $body = $("body");
          
            var waitForTypes = [];
            $.each(types, function(i, type) {
          
              if (typeof $body.data(type) === 'undefined') {
                waitForTypes.push(type);
              }
            });
          
            var isDataReady = waitForTypes.length === 0;
            if (isDataReady) {
              callback();
              return;
            }
          
            // wait for the last type and run this function again for the rest of the types
            var waitFor = waitForTypes.pop();
            $body.on(waitFor, function() {
              // remove event handler - we only want the stuff triggered once
              $body.off(waitFor);
          
              triggerNowOrOnLoaded(waitForTypes, callback);
            });
          }
          <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
          
          <body>Hi!</body>

          【讨论】:

            【解决方案14】:

            当所有 ajax 加载完成时,我正在使用大小检查

            function get_ajax(link, data, callback) {
                $.ajax({
                    url: link,
                    type: "GET",
                    data: data,
                    dataType: "json",
                    success: function (data, status, jqXHR) {
                        callback(jqXHR.status, data)
                    },
                    error: function (jqXHR, status, err) {
                        callback(jqXHR.status, jqXHR);
                    },
                    complete: function (jqXHR, status) {
                    }
                })
            }
            
            function run_list_ajax(callback){
                var size=0;
                var max= 10;
                for (let index = 0; index < max; index++) {
                    var link = 'http://api.jquery.com/ajaxStop/';
                    var data={i:index}
                    get_ajax(link,data,function(status, data){
                        console.log(index)
                        if(size>max-2){
                            callback('done')
                        }
                        size++
                        
                    })
                }
            }
            
            run_list_ajax(function(info){
                console.log(info)
            })
            &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"&gt;&lt;/script&gt;

            【讨论】:

            • 赞你的例子。
            【解决方案15】:

            为了扩展亚历克斯的答案,我有一个带有可变参数和承诺的示例。我想通过 ajax 加载图像并在它们全部加载后显示在页面上。

            为此,我使用了以下内容:

            let urlCreator = window.URL || window.webkitURL;
            
            // Helper function for making ajax requests
            let fetch = function(url) {
                return $.ajax({
                    type: "get",
                    xhrFields: {
                        responseType: "blob"
                    },
                    url: url,
                });
            };
            
            // Map the array of urls to an array of ajax requests
            let urls = ["https://placekitten.com/200/250", "https://placekitten.com/300/250"];
            let files = urls.map(url => fetch(url));
            
            // Use the spread operator to wait for all requests
            $.when(...files).then(function() {
                // If we have multiple urls, then loop through
                if(urls.length > 1) {
                    // Create image urls and tags for each result
                    Array.from(arguments).forEach(data => {
                        let imageUrl = urlCreator.createObjectURL(data[0]);
                        let img = `<img src=${imageUrl}>`;
                        $("#image_container").append(img);
                    });
                }
                else {
                    // Create image source and tag for result
                    let imageUrl = urlCreator.createObjectURL(arguments[0]);
                    let img = `<img src=${imageUrl}>`;
                    $("#image_container").append(img);
                }
            });
            

            更新为适用于单个或多个网址:https://jsfiddle.net/euypj5w9/

            【讨论】:

              【解决方案16】:

              我找到了简单的方法,它使用shift()

              function waitReq(id)
              {
                jQuery.ajax(
                {
                  type: 'POST',
                  url: ajaxurl,
                  data:
                  {
                    "page": id
                  },
                  success: function(resp)
                  {
                    ...........
                    // check array length if not "0" continue to use next array value
                    if(ids.length)
                    {
                      waitReq(ids.shift()); // 2
                    )
                  },
                  error: function(resp)
                  {
                    ....................
                    if(ids.length)
                    {
                      waitReq(ids.shift());
                    )
                  }
                });
              }
              
              var ids = [1, 2, 3, 4, 5];    
              // shift() = delete first array value (then print)
              waitReq(ids.shift()); // print 1
              

              【讨论】:

                【解决方案17】:

                我的解决方法如下

                var request;
                ...
                'services': {
                  'GetAddressBookData': function() {
                    //This is the primary service that loads all addressbook records 
                    request = $.ajax({
                      type: "POST",
                      url: "Default.aspx/GetAddressBook",
                      contentType: "application/json;",
                      dataType: "json"
                    });
                  },
                
                  ...
                
                  'apps': {
                    'AddressBook': {
                      'data': "",
                      'Start': function() {
                          ...services.GetAddressBookData();
                          request.done(function(response) {
                            trace("ajax successful");
                            ..apps.AddressBook.data = response['d'];
                            ...apps.AddressBook.Filter();
                          });
                          request.fail(function(xhr, textStatus, errorThrown) {
                            trace("ajax failed - " + errorThrown);
                          });
                

                工作得很好。我尝试了很多不同的方法来做到这一点,但我发现这是最简单和最可重用的。希望对你有帮助

                【讨论】:

                  【解决方案18】:

                  看看我的解决方案:

                  1.将此函数(和变量)插入到您的 javascript 文件中:

                  var runFunctionQueue_callback;
                  
                  function runFunctionQueue(f, index, callback) {
                  
                    var next_index = index + 1
                  
                    if (callback !== undefined) runFunctionQueue_callback = callback;
                  
                    if (f[next_index] !== undefined) {
                      console.log(index + ' Next function avalaible -> ' + next_index);
                      $.ajax({
                        type: 'GET',
                        url: f[index].file,
                        data: (f[index].data),
                        complete: function() {
                          runFunctionQueue(f, next_index);
                        }
                      });
                    } else {
                      console.log(index + ' Last function');
                      $.ajax({
                        type: 'GET',
                        url: f[index].file,
                        data: (f[index].data),
                        async: false,
                        complete: runFunctionQueue_callback
                      });
                    }
                  }
                  

                  2.根据您的请求构建一个数组,如下所示:

                  var f = [
                             {file: 'file_path', data: {action: 'action', data: 'any_data}},
                             {file: 'file_path', data: {action: 'action', data: 'any_data}},
                             {file: 'file_path', data: {action: 'action', data: 'any_data}},
                             {file: 'file_path', data: {action: 'action', data: 'any_data}}
                          ];
                  

                  3.创建回调函数:

                  function Function_callback() {
                    alert('done');
                  }
                  

                  4.调用带参数的runFunctionQueue函数:

                  runFunctionQueue(f, 0, QuestionInsert_callback);
                  // first parameter: array with requests data
                  // second parameter: start from first request
                  // third parameter: the callback function
                  

                  【讨论】:

                    【解决方案19】:

                    $.when 对我不起作用,callback(x) 而不是 return x 的工作方式如下所述:https://stackoverflow.com/a/13455253/10357604

                    【讨论】:

                      【解决方案20】:

                      以下解决方案使用 $when 对我有用

                      $.when(master.GetStateByName(stateName)).done(function(response) {
                          if (response) {
                      
                          }
                      });
                      
                      GetStateByName: function(stateName) {
                          return $.ajax({
                              type: 'POST',
                              url: getStatesByName + '?stateName=' + stateName,
                              async: false,
                          });
                      }
                      

                      【讨论】:

                        【解决方案21】:

                        这对我有用 很简单

                        return $.ajax({
                          type: 'POST',
                          url: urlBaseUrl
                          data: {someData:someData},
                          dataType: "json",
                          success: function(resultData) { 
                          }
                        });
                        

                        【讨论】:

                        • 不,这不是答案,因为他特别要求所有请求。您的代码很简单,因为它太简单了,它只处理单个请求的响应。请在回答之前阅读问题。
                        【解决方案22】:

                        试试这个方法。在 java 脚本函数中创建一个循环以等待 ajax 调用完成。

                        function getLabelById(id)
                        {
                            var label = '';
                            var done = false;
                            $.ajax({
                               cache: false,
                               url: "YourMvcActionUrl",
                               type: "GET",
                               dataType: "json",
                               async: false,
                               error: function (result) {
                                 label='undefined';
                                 done = true;
                                },
                               success: function (result) {
                                    label = result.Message;
                                    done = true;
                                }
                             });
                        
                           //A loop to check done if ajax call is done.
                           while (!done)
                           {
                              setTimeout(function(){ },500); // take a sleep.
                           }
                        
                            return label;
                        }
                        

                        【讨论】:

                        • 您的setTimeout() 不是take a sleep。在这种情况下,您只需阻止所有选项卡,直到 done 变为 true。
                        • 我认为这是这个主题要求:“等到所有 jQuery Ajax 请求都完成”。
                        • 你测试过这段代码吗?我的期望是,当 while 循环仍在运行时,done 永远不会是真的。如果 while 循环正在运行,则事件循环无法继续,因此永远不会运行回调到 ajax 成功。
                        猜你喜欢
                        • 2015-07-17
                        • 2013-11-03
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多