Best approach for dependent ajax calls in jQuery - javascript

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++]();
}
}
})();

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.

Jquery deferred not behaving as expected

I make 2 ajax calls. Second one should be called only when the first is finished:
var deferred = $.Deferred();
firstAjaxCall();
deferred.done(function () {
secondAjaxCall();
});
function firstAjaxCall() {
$.ajax({
url: '/SomeUrl',
type: 'POST',
success: function () {
deferred.resolve();
}
});
}
function secondAjaxCall() {
$.ajax({
url: '/SomeOtherUrl',
type: 'Get',
});
}
I also tried like this (jQuery deferreds)
$.when(firstAjaxCall()).done(function() {
secondAjaxCall();
});
but no luck.
Still, in the first example, sometimes the second call gets called first, sometimes it doesn't
In the first example the flow is like this:
firstAjaxCall();
secondAjaxCall();
deferred.resolve();
why is second call called first and before deferred.resolve() ?
You have to actually return the Deferred from $.ajax to $.when to make that work
function firstAjaxCall() {
return $.ajax({
url : '/SomeUrl',
type : 'POST'
});
}
function secondAjaxCall(data_from_first) {
return $.ajax({
url : '/SomeOtherUrl',
type : 'Get',
});
}
firstAjaxCall().done(secondAjaxCall);
You can try to call secondAjaxCall() in the success function of the first one
Like this :
function firstAjaxCall() {
return $.ajax({
url: '/SomeUrl',
type: 'POST',
success: secondAjaxCall()
});
}

Event after all ajax calls are complete

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.

Ajax - All request are Done/Completed

I have a difficulty to know when all Ajax requests are completed because I need this information to call another function.
Difficulty are to know when my 4/5 function with requests are completed. I use native function of ajax and none is working for me.
I used Chrome, and async requests.
Someone Helps me
I use this(not work):
$(document).ajaxStop(function() {
alert("Completed");
});
and this (not Work):
$(document).ajaxComplete(function() { alert("Completed"); });
Both ways I try use in another function thal calls all requests:
Example:
function Init()
{ Search("123"); Search2("1234"); Search3("12345");
... }
Extract one (of 5 requests,others are very similar ) of my request:
function Search(user) {
$.ajax({
url: 'www.example.com/' + user,
type: 'GET',
async: true,
dataType: 'JSONP',
success: function(response, textStatus, jqXHR) {
try {
if (response != null) {
alert("Have Data");
} else {
alert("are empty");
}
} catch (err) {
alert("error");
}
},
error: function() {
alert("error");
}
}); }
have you tried putting it in a done function? something like...
$.ajax({
url: 'www.example.com/' + user,
type: 'GET',
async: true,
dataType: 'JSONP'
}).done(function (data) {
code to execute when request is finished;
}).fail(function () {
code to do in event of failure
});
bouncing off what Michael Seltenreich said, his solution, if i understand where you guys are going with this...might look something like:
var count = 0;
function checkCount(){
if(count == 5 ){
//do this, or fire some other function
}
}
#request one
$.ajax({
url: 'www.example.com/' + user,
type: 'GET',
async: true,
dataType: 'JSONP',
}).done( function(data){
count += 1
checkCount()
})
#request two
$.ajax({
url: 'www.example.com/' + user,
type: 'GET',
async: true,
dataType: 'JSONP',
}).done( function(data){
count += 1
checkCount()
})
and do it with your five requests. If that works out for you please make sure to mark his question as the answer;)
You can create a custom trigger
$(document).trigger('ajaxDone')
and call it when ever you finished your ajax requests.
Then you can listen for it
$(document).on('ajaxDone', function () {
//Do something
})
If you want to keep track of multiple ajax calls you can set a function that counts how many "done" values were passed to it, and once all are finished, you can fire the event.
Place the call for this function in each of the 'success' and 'error' events of the ajax calls.
Update:
You can create a function like so
var completedRequests= 0
function countAjax() {
completedRequests+=1
if(completedRequests==whatEverNumberOfRequestsYouNeed) {
$(document).trigger('ajaxDone');
}
}
Call this function on every success and error events.
Then, ajaxDone event will be triggered only after a certain number of requests.
If you wanna track specific ajax requests you can add a variable to countAjax that checks which ajax completed.

problems executing a jquery ajax call within a function

I would like to put an ajax call within a function since I use it repeatedly in multiple locations. I want a manipulated version of the response returned. Here's what I'm trying to do (greatly simplified).
a = getAjax();
$('body').append('<div>'+a+'</div>');
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
return response;
});
}
What's happening, however, is that the append function is running before "a" has been defined in the getAjax function. Any thoughts?
AJAX is asynchronous. This means that the code in the success handler is delayed until the request is successful, while the rest of the code continues as normal. You need to put the relevant code in the AJAX success handler:
getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
$(document.body).append('<div>'+response+'</div>');
});
}
Note that I have also optimised your body selector by using the native Javascript document.body rather than using the standard tag selector.
Edit Callback version
function getAjax(callback) {
$.ajax({
type: 'GET',
url: 'someURL',
success: callback
});
}
You can now do the code inline using a callback function:
getAjax(function(response) {
$(document.body).append('<div>'+response+'</div>');
});
or
getAjax(function(response) {
alert(response);
});
or whatever.
The code inside the anonymous function call will be processed when the AJAX request is complete.
There are two ways to taggle this. one is to use the success callback:
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
AppendResponse(response);
});
the other is to set async to false http://api.jquery.com/jQuery.ajax/:
var a;
getAjax();
$('body').append('<div>'+a+'</div>');
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
async: false,
success: function(response) {
a = response;
});
}
Important note on non async:
Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation.
Why don't you return the response to another function in the success callback. This should handle your need for different responses:
getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
AppendResponse(response);
});
}
function AppendResponse(response) {
$('body').append('<div>'+response+'</div>');
}
One suggestion I have is to pass a trigger to the command you want to run into the AJAX function so that it will run after AJAX has received a response-
a = getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
inputText(response);
});
}
inputText(someText) {
$(document.body).append('<div>'+ someText +'</div>');
}
That way you can create if statements / other alternatives to continue to use the same AJAX command for different results
You can give a handler to the function getAjax(), but if the user needs the information for the next decision then why not wait using async: false?
function getAjax(handler) {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
handler(response);
});
};
function callGetAjax(response) {
if(response === undefined) {
getAjax(callGetAjax);
} else {
$('body').append('<div>'+response+'</div>');
}
}

Categories

Resources