Wait until all jQuery Ajax requests are done?

后端 未结 21 1798
离开以前
离开以前 2020-11-21 04:39

How do I make a function wait until all jQuery Ajax requests are done inside another function?

In short, I need to wait for all Ajax requests to be done before I exe

21条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-11-21 05:33

    I highly recommend using $.when() if you're starting from scratch.

    Even though this question has over million answers, I still didn't find anything useful for my case. Let's say you have to deal with an existing codebase, already making some ajax calls and don't want to introduce the complexity of promises and/or redo the whole thing.

    We can easily take advantage of jQuery .data, .on and .trigger functions which have been a part of jQuery since forever.

    Codepen

    The good stuff about my solution is:

    • it's obvious what the callback exactly depends on

    • the function triggerNowOrOnLoaded doesn't care if the data has been already loaded or we're still waiting for it

    • it's super easy to plug it into an existing code

    $(function() {
    
      // wait for posts to be loaded
      triggerNowOrOnLoaded("posts", function() {
        var $body = $("body");
        var posts = $body.data("posts");
    
        $body.append("
    Posts: " + posts.length + "
    "); }); // 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("
    Posts: " + posts.length + " and Users: " + users.length + "
    "); }); // 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("
    Delayed Users: " + users.length + "
    "); }); }, 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); }); }
    
    
    Hi!

提交回复
热议问题