1

I have a page that loads a lot of data from the database and writes it to the DOM.

Depending on the amount of records, this could take a good 30 seconds or so between receiving the data and printing it to the DOM.

I am curious if there is a way to detect once data has begun downloading / received from the AJAX call?

The reason I ask is I have a loading indicator (spinner gif) on the page that shows that something is happening.

I would like to be able to detect when data has begun downloading and change this to another message, kinda like "Step 2 of 2" so that the user knows it is progressing.

Step 1: On Document Ready, show loader: $('#loading').show();

Step 2: Trigger AJAX call to fetch data

$.ajax({
    url: "api/fetchDashboard",
    type: 'POST',
    cache: false,
    data: {
        dashboardID: dashboardID
    },
    error: function(err) {
        alert(err.statusText);
    },
    success: function(data) {
      // Write data to the DOM here

     // Once done, hide loader
     $('#loading').hide(); 
    }
});

Step 3: Write our data to the DOM and hide the loading indicator

My ask is that once we start receiving the data, detect that and change the loading indicator to something else to state that we have retrieved the data and its being prepared for viewing. enter image description here

Is this possible to detect and trigger another function upon receiving? In the image above, you can see that it is downloading all the data and was thinking that once that counter started, it would be an indication that we have retrieved something back.

Update:

Per ask, this is how I am appending to the DOM, outside of the loop once all the rows have been concatenated.

var output = '',

$.ajax({
    url: "api/fetchDashboardRender",
    type: 'POST',
    cache: false,
    data: {
        dashboardID: dashboardID
    },
    error: function(err) {
        alert(err.statusText);
    },
    success: function(data) {

        // Set our results as a variable
        dashResults = data // Holds the dashboard results

        // Loop over the core data
        $(dashResults['data']['results']['data']).each(function() {
          output += 'Table Row Data Here';
        });

        // Append the results to the DOM
        $('[name=results]').empty().append(output);
    }

});
SBB
  • 8,560
  • 30
  • 108
  • 223
  • This sounds like a very long load. My first suggestion is to show your loader with CSS initially, not use javascript to show it. Second, I believe when ajax sends information, it's pretty instant. it only knows that now it's waiting. Then it will just receive a package ready to use. I don't think ajax "downloads" (with progress) a package. It just gets there all at the same time? I could be wrong. But with what I think, You would just show loading when the page loads, "receiving" when the ajax call is sent (just before your ajax call) and show your data when it's received. – ntgCleaner Dec 08 '16 at 15:03
  • 1
    Why don't you just show `#loading` element when a call is sent? – Kunok Dec 08 '16 at 15:03
  • Possible duplicate of [What is the cleanest way to get the progress of JQuery ajax request?](http://stackoverflow.com/questions/19126994/what-is-the-cleanest-way-to-get-the-progress-of-jquery-ajax-request) – Heretic Monkey Dec 08 '16 at 15:05
  • Hm, well I guess my goal was to try and make the user feel like things were happening. In this long example, it takes about 20 seconds to load all the data from the table (35,000 records) and then X time to write that to the DOM. I wanted to show a change in progress such as (We got your data, now we are preparing it for viewing blah blah. Yes I know loading that amount of data at one time is not a best practice to begin with but that aside, was just checking if that type of function existed in AJAX – SBB Dec 08 '16 at 15:06
  • @SBB Do you know how many records you got before you start writing to the DOM? – Ellery Dec 08 '16 at 15:09
  • I have two things in mind: 1. rewrite your fetchDashboard to send parts of data and a parameter that has value "notdoneyet"/"done" (or 0 and 1, or true/false) and rewrite JS so it checks that value and if NOT "done" (or whatever), send back another ajax call with param "numberofcallssofar=2" (for example) so your fetchDashboard script will return data accordingly (set OFFSET in SQL query or similar). 2. thing that I think of (better solution, if you have the time to dig in) is to use websockets instead AJAX calls. They are made for things like this. – Bozidar Sikanjic Dec 08 '16 at 15:11
  • Instead of doing that, with only 2 steps, why don't you make multiple chained ajax calls, each querying a fixed amount of records (lets say 1000 per call). This way you can make a a nice progress bar. – Alexandru Severin Dec 08 '16 at 15:14
  • 35,000 records? Well, add to SQL query something like -> LIMIT 1000 OFFSET " . $_POST['numberofcallssofar']*1000 . ";"; while changing data: accordingly... – Bozidar Sikanjic Dec 08 '16 at 15:17
  • @epascarello not always. A legacy system allows users to download a spreadsheet of all this data all at once. This new application allows users to specify their data and essentially build their WHERE clause dynamically. Depending on what they are looking for, records could be pretty high in count. This data is written to the DOM so they can manipulate it, mark it up etc and then choose to export it if they want to, from the DOM it self. Issue is if the data is not there and they try searching for a record in the result set that isn't there, then it causes problems, which is why all is provided – SBB Dec 08 '16 at 15:18
  • You can check XMLHttpRequest.readyState, the state will change from 0 to 4, including when the browser starts receiving the data. You can even show the loading % in the loading message. https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState – phobia82 Dec 08 '16 at 15:28
  • That is a load of DOM. You would be better off with a paged preview and move the download to serverside. e.g. select filters, preview results page by page, then press download to get the whole file. Browsers will tend to choke on that much data. – iCollect.it Ltd Dec 08 '16 at 15:31
  • @GoneCoding So in the image, that timer started because it had all the data it needed and was then writing it all to the DOM? – SBB Dec 08 '16 at 15:33
  • Can't say anything for sure without all the code... it just says "Write data to the DOM here" at the moment :) – iCollect.it Ltd Dec 08 '16 at 15:34
  • @GoneCoding It's basically just looping over the data sent and creating a table, one row per record. – SBB Dec 08 '16 at 15:35
  • That can be *very* slow if not done in one single string append (factor of 100 times slower). Please show that code. – iCollect.it Ltd Dec 08 '16 at 15:41
  • @GoneCoding - I have updated the OP with some psuedo code showing that. It does not get appended in the loop, its after. – SBB Dec 08 '16 at 16:37
  • Okay. So that is not the slow part (unless the missing code is particularly slow. Please refer to my first suggestion about separation of the preview from the download. I think the overall process needs changing if it is that slow. – iCollect.it Ltd Dec 08 '16 at 16:53

0 Answers0