How do you use .when (). Then () to run the function when using deferrable objects in .when ()?

I have a page in which I have a variable number of AJAX calls to create that fire on a general event. AJAX calls themselves are updating related fields in an SQL database. When all the calls are completed, I want to refresh the page so that it now reflects the changes just made.

I used the following question / answer to get so far .. jQuery, when each one is complete, the trigger function

Here is my code:

var team_update = function(e) { var $items = $('.sortable-items'); var XHRs = []; $items.each(function(){ var team_id = $( this ).attr("id"); var data = { tid: team_id, users: $('#' + team_id).sortable('toArray') }; XHRs.push( $.ajax({ type: "POST", url: "update.php", data: data, complete: function(data){ } }) ); }); $.when(XHRs).then(function(){ console.log('Refreshing Screen'); $('#content-wrapper').load( 'index.php' ); }); } 

What I was expecting is that $('#content-wrapper').load( 'index.php' ); will fire as soon as all my ajax () requests are complete. What seems to be happening is that the callback starts after all requests have been sent, and not necessarily after they are completed, and therefore sometimes updating my page still contains "old" data.

The graph below shows the initial loading of the page at the top, which can be ignored. His next 4 entries that show the problem. There are 3 POST requests, which are my 3 ajax calls to update the database, and the final GET, which is the page update. A GET page refresh is triggered after all 3 ajax calls have been sent, but it does not wait for the last ajax call to complete before it starts. As a result, it receives the old data as it completes before the previous ajac call completed the database update.

Firebug timeline

What am I doing wrong here?

+4
source share
1 answer

I recently applied something similar.

when() expects a pending object or a list of pending objects, but if you want to use an array, you need to use apply() .

replace

 $.when(XHRs) 

with

 $.when.apply(null, XHRs) 

If this does not work, you may need to wrap the Ajax call in a function:

 function SendAjax(data){ return $.ajax({Options as they are in your ajax call}); } 

and then click them in XHR as such:

 XHRs.push(SendAjax(data)); 

as follows, as I implemented this in my code, you can adapt it if necessary:

 //We want to notify how many memberships have been made after they're all made. since they're async, we'll need to use promises //however, because we repeat the same ajax call with different parameters, we need to push them to an array and then apply() them. checkedBoxes.each(function () { createArray.push(CreateMembershipsAjax(this)); }); //we did the work before we start creating them, so show some progress; add1ToProgress(); $.when.apply(null, createArray).done(function () { //this function will only start once all ajax calls have been successfull. divCreated.append(membershipCount + " memberships created:"); MembershipsCreated = true; window.close(); }); ... CreateMembershipsAjax(element){ //process element, create Data from it; return $.ajax({option}); } 

And yes, the comments are indeed in my code, and not just added for clarification on this page.

+5
source

Source: https://habr.com/ru/post/1385694/


All Articles