Event after all ajax calls are complete - javascript

I have a click event that fires off 3 ajax calls:
$("#button").click(function(e) {
e.preventDefault();
$.ajax(call1);
$.ajax(call2);
$.ajax(call3);
some_function() //should fire off AFTER all ajax calls are complete
});
Is there a way for me to confirm all ajax calls have been fired BEFORE firing off my some_function() function?
Thanks in advance!

You can use $.when
Provides a way to execute callback functions based on one or more objects, usually Deferred objects that represent asynchronous events.
$.when($.ajax(call1), $.ajax(call2), $.ajax(call3))
.done(function () {
some_function();
});
If (for some reason) you have an array of promises, then you may call this method using Function.prototype.apply():
$.when.apply($, ajaxArray)
.done(function () {
some_function();
});

I suggest you to use async: false and put the $.ajax inside another ajax, somelike this...
$.ajax({
async: false,
// ...
complete: function() {
$.ajax({ // second ajax
async: false,
// ...
complete: function() {
$.ajax({ // second ajax
async: false,
// ...
complete: function() {
some_function();
}
});
}
});
}
});

It depends if you require success responses, but consider the following:
$.ajax({
url: "http://some.url.example.com/endpoint",
})
.always(function (data){
// Process the data
$.ajax({
url: "http://some.url.example.com/endpoint2",
})
.always(function (data2){
// Process the data
$.ajax({
url: "http://some.url.example.com/endpoint3",
})
.always(function (data) {
someFunction();
});
});
});
There is a lot more reading that could be done about jQuery deferred objects and ES6 Promises.
If you wish to set a timeout and don't care about the result, set the timeout option `$.ajax({url: "http://some.url.example.com/endpoint", timeout: 500})
OR
Set a variable in each and use window.setTimeout to check when they've all been set, but that is horrible.

Related

Promise and callback function in ajax, when does success take place ?

Right now I have a code like this:
$.ajax({
url: apiUrl + valueToCheck,
data: {
format: 'json'
},
error: function () {
},
dataType: 'json',
success: function (data) {
checkAgainstDBHelperWH(data, valueToCheck);
},
type: 'GET'
});
If I am not mistaken, checkAgainstDBHelperWH is known as a callback function. The function executes once the servers sends back response for this particular HTTP /ajax request.
I want to try writing something like the one below, but I don't know what are the effects or is it even logical:
var request = $.ajax({
url: apiUrl + valueToCheck,
data: {
format: 'json'
},
error: function () {
},
dataType: 'json',
success: function (data) {
checkAgainstDBHelperWH(data, valueToCheck);
},
type: 'GET'
})
arrayOfPromises.push(request);
$.when.apply(null, arrayOfPromises).done(function () {
//...some javascript here
});
I want to understand if the .done(function () is fired after the callback function checkAgainstDBHelperWH is completed? Or whatever I am trying to write above does not flow consistently with how ajax works?
Thanks!
I tested it, your code only work if the function(in this case, 'checkAgainstDBHelperWH') doesn't call ajax.
If you want to wait finishing the inner ajax process, use then() and return inner ajax.
var ajaxs =
$.get("xxx").then(function() {
return $.get("yyy").done(function() {
});
});
Here is the jsfiddle.
I'm not sure whether this way is general or not.

Wait until all Ajax finish processing inside another Ajax, then send data

I'm trying to send data off with data from multiple other Ajax requests. The issues comes when sendDataOffAjax() is called, no actual data was sent, because it fires off before any of the other functions have a change to add data. I could easily fix this by just using asyn: false everywhere, but from what I read, that's bad practice.
Here is my code:
let requests = [];
$.ajax({
url: someUrl,
method: 'GET',
dataType: 'json',
complete: function (data) {
if (data.exists) {
if (condition) {
requests.push(anotherAjax());
}
if (condition) {
requests.push(someDifferentAjax());
}
}
requests.push(alwaysRunAjax());
}
}).done(function () {
$.when.apply($, requests).done(function () {
sendDataOffAjax();
});
});
Heres what anotherAjax() looks like (All the other Ajax requests also look like this):
function anotherAjax() {
return $.ajax({
url: someUrl,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'GET',
dataType: 'json',
complete: function (data) {
if (data.exists) {
toSendData.data['NEW_DATA'] = {
'data': data.responseJSON
}
}
//send complete signal?
}
})
}
How could I make it wait until all the data is added through the other Ajax requests, then launch sendDataOffAjax().
The log looks like this:
Data sent
anotherAjax Data added
alwaysRunAjax Data added
someDifferentAjax Data added
When it comes to ajax requests, .complete(), according to jQuery's docs, runs only after the success or error callback is run and .done() is the same as calling .success(). So with this in mind you can see why the code in your done callback is running first. You should be able to switch the code from your complete callback to your done callback and vice-versa to get the desired effect.
So Try:
let requests = [];
$.ajax({
url: someUrl,
method: 'GET',
dataType: 'json',
complete: function () {
$.when.apply($, requests).done(function () {
sendDataOffAjax();
});
}
}).done(function (data) {
if (data) {
if (condition) {
requests.push(anotherAjax());
}
if (condition) {
requests.push(someDifferentAjax());
}
}
requests.push(alwaysRunAjax());
});
Now, as long as all of your ajax functions you are calling here return deferred objects your requests array should be filled and $.when() should wait until all the deferred objects resolve.
No this isn't possible without async:false.
The reason it doesn't count as a good thing to use is becuase it is against the idea of a Ajax which is Asynchronous.
async:false baisiclly "lock" your application to the user until your request is done and when you put it on too much ajax calls in the same time it will make your apllication seems very very slow.
In your case you it will be fine if you'll use async:false on the 2 functions as long as they don't take long to execute.

ajax request is not stopping

Here is my ajax call:
$.ajax({
url: "AutoRFQ_Vendors_ST.aspx/BindVesselGrid",
type: "POST",
timeout: 3000,
data: JSON.stringify(sendingdata),
contentType: "application/json",
success: function (data) {
//do something
}
Here is my CSS loader:
ajaxStart: function () { $body.addClass("loading"); },
ajaxStop: function () { $body.removeClass("loading"); }
When I make an ajax call which responds d:'' an empty string but my ajaxstop: event is not firing.
You have to hide your loader on ajax() complete like:
ajax({
complete: function(){
$body.removeClass("loading");
}
});
complete executes after either the success or error callback were executed.
You need to understand that the ajaxStart and the ajaxStop events falls under global event handlers in jQuery. Hence you need to hook them to document instead of having in your $ajax call.
You need to rewrite your code as,
$(document)
.ajaxStart(function () {
$body.addClass("loading");
})
.ajaxStop(function () {
$body.removeClass("loading");
});
Hope this helps!

Best approach for dependent ajax calls in jQuery

I have a situation where I need to make 5 ajax calls. The second ajax call will be made after first call returns response, the third call is made when second call completes and likewise fourth and fifth call.
There are 2 approach for this which I know, I could nest ajax calls on success of previous call or make async false before first call and make it true after last call. Could any one suggest which is and WHY it is the better way to accomplish my task or there is some more better way to do this.
//First Way
$.ajax({
...
success:function(){
$.ajax({
...
success:function(){
$.ajax({
...
success:function(){
$.ajax({
...
success:function(){
do something
}
});
}
});
}
});
}
});
//second way
$.ajaxSetup({
async: false
});
$.ajax({
});
$.ajax({
});
$.ajax({
});
$.ajax({
});
$.ajax({
});
$.ajaxSetup({
async: true
});
Could any one suggest which is and WHY it is the better way to accomplish my task...
Using async: false will make the calls synchronous, which locks up the UI of the browser while the calls are running. It's better to leave the UI responsive while the calls are running.
So leaving the calls asynchronous is best; there are a few ways to do that:
There's using the success handler, as you demonstrated:
$.ajax({
/*...*/,
success: function() {
$.ajax({
/*...*/,
success: function() {
$.ajax({
/*...*/,
success: function() {
$.ajax({
/*...*/,
success: function() {
$.ajax({
/*...*/
});
}
});
}
});
}
});
}
});
(I'm assuming you've either registered a global ajax error handler, or that you have one in /*...*/ above.)
There's using a promise chain instead, which is quite similar:
$.ajax({/*...*/})
.done(function() {
$.ajax({/*...*/})
.done(function() {
$.ajax({/*...*/})
.done(function() {
$.ajax({/*...*/})
.done(function() {
$.ajax({/*...*/});
});
});
});
});
Or you can use a function loop, like so:
(function() {
var calls = [
function() { $.ajax({/*...*/, success: next)},
function() { $.ajax({/*...*/, success: next)},
function() { $.ajax({/*...*/, success: next)},
function() { $.ajax({/*...*/, success: next)},
function() { $.ajax({/*...*/, success: next)}
];
var index = 0;
next();
function next() {
if (index < calls.length) {
// Do the next, increment the call index
calls[index++]();
}
}
})();

jQuery Deferred - Adding a callback to the Deferred contract

I'm trying to add another asynchronous call to the contract of an existing Deferred before its state is set to success. Rather than try and explain this in English, see the following pseudo-code:
$.when(
$.ajax({
url: someUrl,
data: data,
async: true,
success: function (data, textStatus, jqXhr) {
console.log('Call 1 done.')
jqXhr.pipe(
$.ajax({
url: someUrl,
data: data,
async: true,
success: function (data, textStatus, jqXhr) {
console.log('Call 2 done.');
},
})
);
},
}),
$.ajax({
url: someUrl,
data: data,
async: true,
success: function (data, textStatus, jqXhr) {
console.log('Call 3 done.');
},
})
).then(function(){ console.log('All done!'); });
Basically, Call 2 is dependent on the results of Call 1. I want Call 1 and Call 3 to be executed in parallel. Once all 3 calls are complete, I want the All Done code to execute. My understanding is that Deferred.pipe() is supposed to chain another asynchronous call to the given deferred, but in practice, I always get Call 2 completing after All Done.
Does anyone know how to get jQuery's Deferred to do what I want? Hopefully the solution doesn't involve ripping the code apart into chunks any further.
Thanks for any help.
UPDATE: Please see my follow up question.
You have to call .pipe on the deferred object returned by the first $.ajax call, not inside its success callback (this does not have any effect at all):
$.when(
$.ajax({
// ...
}).pipe(function() {
// return a deferred object from .pipe
return $.ajax({
// ...
});
}),
$.ajax({
// ...
})
).done(function(){ console.log('All done!'); });
.pipe returns a new deferred object which only gets resolved once both, the original deferred object and the returned one get resolved.

Categories

Resources