Wait until all jQuery Ajax requests are done?
jQuery now defines a when function for this purpose.
It accepts any number of Deferred objects as arguments, and executes a function when all of them resolve.
That means, if you want to initiate (for example) four ajax requests, then perform an action when they are done, you could do something like this:
$.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,
...
});
}
In my opinion, it makes for a clean and clear syntax, and avoids involving any global variables such as ajaxStart and ajaxStop, which could have unwanted side effects as your page develops.
If you don't know in advance how many ajax arguments you need to wait for (i.e. you want to use a variable number of arguments), it can still be done but is just a little bit trickier. See Pass in an array of Deferreds to $.when() (and maybe jQuery .when troubleshooting with variable number of arguments).
If you need deeper control over the failure modes of the ajax scripts etc., you can save the object returned by .when()
- it's a jQuery Promise object encompassing all of the original ajax queries. You can call .then()
or .fail()
on it to add detailed success/failure handlers.
Wait until all Ajax requests in a for loop are done before moving on?
I think the problem is that you are calling $.wait
right after getSuites()
is executed.
$.wait
'sees' the ajaxCalls
array empty (because getSuites()
hasn't finish yet) and executes doneCallback()
.
Try to call $.wait
INSIDE the suitesJSON.done
function, that way it will be called after the ajaxCalls
array is filled with the first response:
myConnector.getData = function (table, doneCallback) {
console.log("Getting Data...");
var ajaxCalls = [], tableData = [];
var suitesJSON = getSuites();
suitesJSON.done(function(data) {
var suites = data.QueryResult.Results;
for(var i = 0; i < suites.length; i++) {
(function(i) {
var defectsJSON = getDefects(suites[i].Defects._ref + "?fetch=Name,FormattedID,State,Priority,CreationDate,c_RootCause,c_RootCauseCRM");
ajaxCalls.push(defectsJSON);
defectsJSON.done(function(data) {
var defects = data.QueryResult.Results;
for(var j = 0; j < defects.length; j++) {
tableData.push({
"suiteName": suites[i].Name, // This is the name of the suite collected in the outer call
"defectName": defects[j].Name,
"FormattedID": defects[j].FormattedID,
"State": defects[j].State,
"Priority": defects[j].Priority,
"CreationDate": defects[j].CreationDate,
"RootCause": defects[j].c_RootCause,
"RootCauseCRM": defects[j].c_RootCauseCRM
});
}
});
})(i);
}
$.when.apply($, ajaxCalls).then(function() {
console.log(tableData);
table.appendRows(tableData);
doneCallback();
});
});
};
How do I make jQuery wait for an Ajax call to finish before it returns?
If you don't want the $.ajax()
function to return immediately, set the async
option to false
:
$(".my_link").click(
function(){
$.ajax({
url: $(this).attr('href'),
type: 'GET',
async: false,
cache: false,
timeout: 30000,
fail: function(){
return true;
},
done: function(msg){
if (parseFloat(msg)){
return false;
} else {
return true;
}
}
});
});
But, I would note that this would be counter to the point of AJAX. Also, you should be handling the response in the fail
and done
functions. Those functions will only be called when the response is received from the server.
JavaScript - Wait until multiple ajax requests are done then do something
Store the promises returned by $.ajax in variables and use Promise.all()
const req1 = $.ajax('https://jsonplaceholder.typicode.com/todos/1').then(data => {
console.log('First request done')
return data
})
const req2 = $.ajax('https://jsonplaceholder.typicode.com/todos/2').then(data => {
console.log('Second request done')
return data
})
Promise.all([req1, req2]).then(results=>{
console.log('All done')
console.log('Combined results',results)
}).catch(err=> console.log('Ooops one of the requests failed'))
.as-console-wrapper {max-height: 100%!important;top:0;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Wait until unknown number of ajax request done
First of all, you know how many files are uploaded, so you know how many ajax request you are doing. (1 Request per file)
So before your $.each()
fires you get the size of files
let count = $(files).size();
$.each(files,function(idx,elm){
/*your code with requests*/
}
Now, after each ajax request hast fired, decrement count
. Decrement inside your success
and failure
methods, because it doesn't mattet if it succeeded or not. And check if count === 0
. If it's 0 than you know all ajax are done.
$.ajax({
/*your other settings*/
success: function (data) {
alert(data);
count--;
doSomething(count);
},
failure: function (request) {
console.log(request);
count--;
doSomething(count);
},
});
function doSomething(count){
if(count === 0){
/*stuff you wannna do after all ajax requests are done*/
}
}
I haven't done that many ajax for now, so I'm not quite sure if failure
is also fired on error
, but if not maybe add count--
and the if on error as well.
jQuery wait until Ajax call has got data before displaying
Return the $.ajax
promise from get_values()
and use $.when()
to run when all the requests have completed
/* Get Values */
function get_values(id) {
var settings = {
"async": true,
"crossDomain": true,
"url": "example.com",
"method": "GET",
"headers": {
"Accept": "application/json",
},
"dataType": "json",
"mimeType": "multipart/form-data",
}
return $.ajax(settings)
}
var req1 = get_values(1),
req2 = get_values(2),
req3 = get_values(3);
$.when(req1, req2, req3).done(function(data_1, data_2, data_3) {
$(".content_loader").fadeOut(function() {
$(".main_container").html('<div class="results">' + data_1 + data_2 + data_3 + '</div>');
});
})
Waiting until all ajax calls are finished not working with $.when
Ok, big refactoring of your code, but I think this will do what you want - sorry I can't test it - I'll attempt to add comments slowly to explain the code
function init(i) {
// $('input.artist') - as I can't see your HTML, I would recommend adding cclass='artist' to inputs that you want to process
// [].map.call($('input.artist'), function(artist, i) { - iterate through the inputs, calling the function which returns a promise
// artistP will be an array of Promises
var artistsP = [].map.call($('input.artist'), function(artist, i) {
console.log('searchArtists for relevant artist ' + $('input')[i].value)
var artist = $('input')[i].value;
// return the promise returned by $.ajax
return $.ajax({
url: 'https://api.spotify.com/v1/search',
data: {
q: artist,
type: 'artist'
}
})
// the returned promise needs to wait for the promise returned by searchRecommendations
.then(function(response) {
console.log(response.artists.href);
return searchRecommendations(response.artists.items[0].id, 0);
});
});
// wait for the promises to complete and we're done
$.when.apply($, artistsP).done(function() {
convert_artists_to_nodes_and_links(ARTISTS)
});
}
function searchRecommendations(artist, depth) {
console.log('searchRecommendations ' + artist + ' ' + depth)
if (depth == MAX) {
// just return undefined to stop the recursion
return console.log('max reached ' + depth);
} else {
// return a promise
return $.ajax({
url: 'https://api.spotify.com/v1/artists/' + artist + '/related-artists',
data: {
type: 'artist',
}
})
// the promise needs to wait for the recursed artists
.then(function(response) {
// create an array of promises to wait on
var promises = response.artists.map(function(artist) {
console.log(artist.name)
var obj = {
'artist': artist.name,
'level': (depth + 1) * 5
}
ARTISTS.push(obj)
return searchRecommendations(response.artists[r].id, depth + 1) //Recursion
});
// return a promise that waits for all the "sub" requests
return $.when.apply($, promises);
});
}
}
How to wait until multiple ajax requests are done?
Use Promise.all()
.
var promises = [];
promises.push(new Promise(done=>{
$.ajax({
url: 'first.php',
async: true,
success: done
});
}));
promises.push(new Promise(done=>{
$.ajax({
url: 'second.php',
async: true,
success: done
});
}));
promises.push(new Promise(done=>{
$.ajax({
url: 'nth.php',
async: true,
success: done
});
}));
Promise.all(promises).then(()=>{
console.log("All ajax completed.");
});
Wait for all Ajax request in each-loop
Use Promise.all
, which will only fire the .then
when all promises it is passed have completed:
let requests = [];
$(data).each(function(index, item) {
let request = $.ajax({
url: "someUrl.com/someData?Id=" + item.id,
success: function(result) {
someFunction(result);
}
});
requests.push(request);
});
Promise.all(requests).then(() => anotherFunction());
Related Topics
Aren't Promises Just Callbacks
What Is the Purpose of a Self Executing Function in JavaScript
What Does "This" Refer to in Arrow Functions in Es6
Pretty-Print Json Using JavaScript
Events Triggered by Dynamically Generated Element Are Not Captured by Event Handler
Xml Parsing of a Variable String in JavaScript
How to Print a Circular Structure in a Json-Like Format
Map Function For Objects (Instead of Arrays)
Safely Turning a Json String into an Object
How to Trigger Event in JavaScript
When Should I Use Curly Braces For Es6 Import
Get the Highlighted/Selected Text
How to Get the Current Date in JavaScript
How to Force Js to Do Math Instead of Putting Two Strings Together