1

I am having some ordering issues. I have some code that does the following: on page load, loop through 3 tables and grab content from server and populate table with said content make the table responsive

I am having issues making this work. I can achieve this fine through inspect element (calling functions) but that's not user friendly. I want to know if there's a way I can choose the ordering on what function is being executed. What I have so far is:

$(document).ready(function() {
    if (dateCounter == null){ //start calendar from today's date
        var current = new Date();
        dateChange(current, "", 0); //function one to get grab all contents

        //make table responsive
        var switched = false;
              var updateTables = function() {
                if (($(window).width() < 992) && !switched ){
                    console.log("window width < 992px");
                  switched = true;
                  $("table.responsive").each(function(i, element) {
                      console.log("splitting table up");
                    splitTable($(element));
                  });
                  return true;
                }
                else if (switched && ($(window).width() > 992)) {
                  switched = false;
                  $("table.responsive").each(function(i, element) {
                    unsplitTable($(element));
                  });
                }
              };
        function splitTable(original){...}
        function unsplitTable(original){...}
    }
});

In theory, on page load, it should populate the table first, then make the table responsive, but that's not the case. It seems to be rendering everything concurrently and therefore I get lots of missing/hidden content in my table. I don't know if the AJAX call in my dateChange function has anything to do preventing my table from displaying content correctly.

Following is a code snippet of the dateChange function:

function dateChange(dateInput, nGuests, vName){
    //format dates
    //For each table (3 tables)
    $(".title").each(function(index, element) {
    //prepare HTML for grabbing content from server
        //Grab content from server and pop into table
        $.ajax({
          url: "/grab_Content.asp?boatType="+boatName+"&date="+dateInput+"&guests="+guests+"&boatName="+vName+"",
          dataType:"html",
          success: function(data){
              table.html(data);
          }
        });
    });
}
Akira Dawson
  • 1,247
  • 4
  • 21
  • 45

1 Answers1

1

Yes, AJAX calls are asynchronous. $.ajax returns a promise that you can use to control sequence. First, return the promise from dateChange:

function dateChange(dateInput, nGuests, vName){
    return $.ajax({
      //...
    });
}

Then when you call it:

dateChange(current, "", 0).then(function() {

    //make table responsive
    var switched = false;
    //....
}

That will make sure the AJAX call completes before you make the table responsive.

If you have multiple AJAX calls, you'll have to store the promises in an array and use $.when:

var promises = [];
$('.whatever').each(function() {
    var promise = $.ajax({ /*...*/ });
    promises.push(promise);
});

$.when.apply($, promises).done(function() {
    console.log('all done');
    // do work....
});

Note we have to use Function.prototype.apply because $.when treats an array of promises like a single promise.

Ethan Brown
  • 26,892
  • 4
  • 80
  • 92
  • I like this approach, but upon making those changes and running the code, I'm met with the error "Uncaught TypeError: Cannot read property 'then' of undefined" which relates to "dateChange(current, "", 0).then(function() {" – Akira Dawson Mar 16 '15 at 22:26
  • What version of jQuery are you using? – Ethan Brown Mar 16 '15 at 22:28
  • Either you're using a version of jQuery prior to 1.8, or you're not returning the promise from the `dateChange` function.... – Ethan Brown Mar 16 '15 at 22:29
  • I'm using version 1.9.1 – Akira Dawson Mar 16 '15 at 22:30
  • I also have this: return $.ajax({ url: "/availability_Dev/availability_Dev.asp?boatType="+boatName+"&date="+dateInput+"&guests="+guests+"&boatName="+vName+"", dataType:"html", success: function(data){ table.html(data); } }); – Akira Dawson Mar 16 '15 at 22:30
  • Sorry for bad formatting, mind you that $.ajax is in a .each() which means it's being called 3 times. I would imagine that would cause some issues – Akira Dawson Mar 16 '15 at 22:31
  • So you want all three AJAX requests to complete before you run the responsive code? – Ethan Brown Mar 16 '15 at 22:33
  • Yes that is correct. Sorry for not specifying earlier. I have 3 tables which I need to populate first, then make responsive – Akira Dawson Mar 16 '15 at 22:33
  • I corrected a mistake; `$.when`, irritatingly, doesn't treat an array of promises as a list of promises to wait for, so you have to use `Function.prototype.apply`. – Ethan Brown Mar 16 '15 at 22:59
  • The ordeal with the promises array, is that code I put in my dateChange() function? I only say because I still get the "Uncaught TypeError: Cannot read property 'then' of undefined" which I stated previously – Akira Dawson Mar 16 '15 at 23:00
  • mind you in the dateChange() function, I added the responsive code in the $.when and I seem to be getting somewhere! Which is something. Which means I don't need the dateChange().then(function(){}); – Akira Dawson Mar 16 '15 at 23:04
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/73179/discussion-between-ethan-brown-and-akira-dawson). – Ethan Brown Mar 17 '15 at 16:12