I have a nested ajax requests. The first request returns a list with devices, for each device i do another ajax request to fetch more data. When the nested request is a success i'm appending the data to a <table>.
I need some kind of event that tells me when all requests are complete. How can i do this? See my code below
$.ajax({
type: 'GET',
url: '#Url.Content("~/Service/listAllDevices")',
dataType: 'json',
success: function (data) {
$.each(data.devices.device, function (index, value) {
$.ajax({
type: 'GET',
url: '#Url.Content("~/Service/listLokationLabelsForDevice")' + '?uuid=' + value.uuid,
dataType: 'json',
success: function (data3) {
//Append to table
}
});
});
You can use promises and $.when() to see when all your ajax calls have completed like this:
$.ajax({
type: 'GET',
url: '#Url.Content("~/Service/listAllDevices")',
dataType: 'json',
success: function (data) {
var promises = [];
$.each(data.devices.device, function (index, value) {
promises.push($.ajax({
type: 'GET',
url: '#Url.Content("~/Service/listLokationLabelsForDevice")' + '?uuid=' +
value.uuid,
dataType: 'json',
}));
});
$.when.apply($, promises).done(function() {
// all ajax results are done here
// results from each ajax call are in order in
// arguments[0], arguments[1], ...
// you can now append them all to the table
});
}
});
The basic idea is that you collect the returned promise from each ajax call into an array. You then use jQuery's $.when to have jQuery tell you when all those promises are resolved and to collect all the returned results from them and to keep all the data in the order you requested it in. Then, when the .done() callback from $.when() is called, all the data is available and you can process it all at once, in order.
Note, I've also removed the success handler from the inner ajax call since you can process all the results in the .done() handler.
The event you're looking for is ajaxStop.
$(document).on('ajaxStop', function() {
//do something
});
Reference:
- http://api.jquery.com/ajaxstop/
Related
I'm having trouble with POST and GET request. On my server side right up until the moment before I send I have what I expect but then on my client side I get things out of order. For example these two should be in the reverse order I have here:
Sending from server{"grid":["","","","","","","","",""],"winner":""}
Received at server: {"grid":["X","","","","","","","",""],"winner":""}
function sendData(json) {
$.ajax({
type: "POST",
url: "/ttt",
data: json,
dataType: "json",
success: receiveData()
});
}
function receiveData() {
var response = $.ajax({
type: "GET",
url: "/ttt",
dataType: "json",
success: function(){
grid = response.responseJSON;
console.log("Receved at client: " + JSON.stringify(grid));
}
});
console.log("Also after receiving " + JSON.stringify(grid));
}
gives me:
Also after receiving {"grid":["X","","","","","","","",""],"winner":""}
Receved at client: {"grid":["X","O","","","","","","",""],"winner":""}
I think this may two different problems. One for getting things out of order and another for why my grid doesnt reflect the changes after my success clause function in my GET request.
You're making a common mistake. You need to use a function reference without the parens here for receiveData. Change this:
function sendData(json) {
$.ajax({
type: "POST",
url: "/ttt",
data: json,
dataType: "json",
success: receiveData()
});
}
to this:
function sendData(json) {
$.ajax({
type: "POST",
url: "/ttt",
data: json,
dataType: "json",
success: receiveData // no parens here
});
}
When you include the parens, it calls the function IMMEDIATELY and puts the return value from the function as the success handler and thus you see them run out of order. You want to pass a function reference to it can be called later. A function reference is the function's name without the parens.
It also appears like you have another mistake in receiveData(). You are using the wrong thing for the response. The response is not returns from $.ajax(). The response is passed to the success handler.
I don't know exactly what your response is supposed to look like, but change this:
function receiveData() {
var response = $.ajax({
type: "GET",
url: "/ttt",
dataType: "json",
success: function(){
grid = response.responseJSON;
console.log("Receved at client: " + JSON.stringify(grid));
}
});
console.log("Also after receiving " + JSON.stringify(grid));
}
to something like this:
function receiveData() {
$.ajax({
type: "GET",
url: "/ttt",
dataType: "json",
success: function(response){
grid = response.responseJSON;
console.log("Received at client: " + JSON.stringify(grid));
console.log("Also after receiving " + JSON.stringify(grid));
}
});
}
And, because your ajax calls are asynchronous, you also had this statement console.log("Also after receiving " + JSON.stringify(grid)); in the wrong place. If you want to see the results of the grid after you've modified it, then you have to put that inside the success handler.
Summary of Fixes
Change success: receiveData() to success: receiveData.
Use response as it is passed to the success handler.
Put console.log() to see final results inside the success handler.
It appears that you may not fully understand how ajax calls are asynchronous and what that really means for your programming. I'd suggest doing some searching and reading on that topic. Learning that now will save you a lot of agony as you develop.
I'm sending ajax call and getting an answer that I need from the first ajax then I want to pass my result to my nested ajax, my var (result) is null in the nested ajax/settimeout fun, can I pass it ? Am I missing something ?
$.ajax({
url: '#Url.Action("getCustomerGuidId", "Document")',
type: 'POST',
cache: false,
data: { "classNum": currentclassNum},
contentType:'json' ,
dataType:'text',
success: function (result) {
alert(result);**-> is fine - not null**.
// a or result is null when I hit the getCurrentDoc- function althought I get the data I need from getCustomerGuidId function
var a = result;-> tried to pass it to a new var..IDK.. I
thought it will help... it didn't.
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
contentType:'text',
data: a,-> here it's null
success: function (data) {
}
});
}, 2000);
},
error: function (result) {
alert("fail " + result);
}
});
You can try something like this will help to pass value to nested ajax call
function test(){
var myText = 'Hello all !!';
$.get({
//used the jsonplaceholder url for testing
'url':'https://jsonplaceholder.typicode.com/posts/1',
'method':'GET',
success: function (data) {
//updating value of myText
myText = 'welcome';
$.post({
'url':'https://jsonplaceholder.typicode.com/posts',
'method':'POST',
//data.title is the return value from get request to the post request
'data':{'title':data.title},
'success':function (data) {
alert(data.title +'\n' + myText);//your code here ...
}
});
}
});
}
An old question and you've likely moved on, but there's still no accepted answer.
Your setTimeout takes an anonymous function, so you are losing your binding; if you have to use a Timeout for some reason, you need to add .bind(this) to your setTimeout call (see below)
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
contentType:'text',
data: a,
success: function (data) {
}
});
}.bind(this), 2000);
At a guess you're using a Timeout because you want to ensure that your promise (i.e. the first ajax call) is resolving prior to making the nested call.
If that's your intention, you can actually scrap setTimeout completely as you have the nested call in the first ajax success call, which only runs once the promise has been resolved (providing there isn't an error; if so, jQuery would call error rather than success)
Removing setTimeout means you won't lose your binding, and a should still be result (hopefully a is an object, otherwise your second call is also going to experience issues...)
Lastly, after overcoming the binding issue you wouldn't need var a = result; you should be able to pass result directly to your nested ajax call.
Good luck!
In the nested ajax you send a as a param name, not as a param value.
So you can try the following (change param to actual param name which your server expects):
$.ajax({
url: '#Url.Action("getCustomerGuidId", "Document")',
type: 'POST',
cache: false,
data: { "classNum": currentclassNum},
dataType:'text',
success: function (result) {
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
data: {param: result},
success: function (data) {
}
});
}, 2000);
},
error: function (result) {
alert("fail " + result);
}
});
I am working with google map.My map data come from php using ajax response.
My ajax code:
<script type="text/javascript">
$.ajax({
type: "POST",
url: "mapajax.php",
dataType:'text',
success: function (result) {
console.log(result);
}
});
</script>
Now I have need to put my response data in my map var location
function initialize() {
var locations = [
//Now here I put my ajax response result
];
How can I do that?
You'll have to refactor your code a little. I'm assuming you call initialize from the success callback.
Pass the locations array as an argument to initialize.
function initialize(locations) { ... }
$.ajax({
type: "POST",
url: "mapajax.php",
dataType:'text',
success: function (result) {
initialize(result);
}
});
Then you can cut down even more and just do success: initialize, as long as initialize doesn't expect other parameters.
Here is a fiddle with an example using $.when but its for SYNTAX only not making the call
http://jsfiddle.net/2y6689mu/
// Returns a deferred object
function mapData(){ return $.ajax({
type: "POST",
url: "mapajax.php",
dataType:'text'
});
}
// This is the magic where it waits for the data to be resolved
$.when( mapData() ).then( initialize, errorHandler );
EDIT** function already returns a promise so you can just use
mapData().then()
per code-jaff comments
This is done using callbacks, http://recurial.com/programming/understanding-callback-functions-in-javascript/ , here's a link if you want to read up on those. Let's see your current code here:
<script type="text/javascript">
$.ajax({
type: "POST",
url: "mapajax.php",
dataType:'text',
success: function (result) {
console.log(result);
}
});
</script>
As you noticed, the 'result' data is accessible in the success function. So how do you get transport it to another function? You used console.log(result) to print the data to your console. And without realizing it, you almost solved the problem yourself.
Just call the initialize function inside the success function of the ajax call:
<script type="text/javascript">
$.ajax({
type: "POST",
url: "mapajax.php",
dataType:'text',
success: function (result) {
initialize(result);
}
});
</script>
Is expected dataType response from $.ajax() to mapajax.php call text ?
Try
$(function () {
function initialize(data) {
var locations = [
//Now here I put my ajax response result
];
// "put my ajax response result"
// utilizing `Array.prototype.push()`
locations.push(data);
// do stuff
// with `locations` data, e.g.,
return console.log(JSON.parse(locations));
};
$.ajax({
type: "POST",
url: "mapajax.php",
dataType: 'text',
success: function (result) {
initialize(result);
}
});
});
jsfiddle http://jsfiddle.net/guest271314/maaxoy91/
See
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push
I have a webpage where I have 3 separate ajax calls
All 3 use the same structure:
$.ajax({
//this is the php file that processes the data and send mail
url: url,
//POST method is used
type: "POST",
//pass the data
data: data,
//Do not cache the page
cache: false,
//success
success: function (json) {
I want to trigger another function but only if the 3 separate ajax calls are successful.
How do I go about doing that?
Update:
I now have an issue when using $.when()
My code now looks like this:
function mainFunction() {
$.when(someAjaxCall()).done(function(ajaxResult){
// after all the pages, covers, and sneaks are uploaded
// we will now change the status
//start the ajax
console.log(ajaxResult);
}
function someAjaxCall() {
// do something...
if (someGlobalScopedVariable == true) {
return $.ajax({
//this is the php file that processes the data and send mail
url: url,
//POST method is used
type: "POST",
//pass the data
data: data,
//Do not cache the page
cache: false,
//success
success: function (json) {....},
});
}
}
The ajaxResult inside the mainFunction $.when gives me undefined.
Did I do something wrong because i followed this http://api.jquery.com/jQuery.when/
Use jQuery.when.
var deferred1 = $.ajax({ ... });
var deferred2 = $.ajax({ ... });
var deferred3 = $.ajax({ ... });
$.when(deferred1, deferred2, deferred3).then(
function(info1, info2, info3) {
var response1 = info1[0], response2 = info2[0], response3 = info3[0];
// Do something with response 1, 2, and 3...
}
);
$.ajax returns a Deferred object. You can pass several Deferred objects to $.when in order to wait for all of them to complete.
Let's say for example, I have the following javascript function that returns a boolean:
function CallWebServiceToUpdateSessionUser(target, user)
{
var dataText = { "jsonUser": JSON.stringify(user) };
$.ajax({
type: "POST",
url: target,
data: JSON.stringify(dataText),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response)
{
return true;
},
failure: function (msg)
{
return false;
}
});
}
and the target function on the server that is being called could take up to... 15 seconds to respond.
How do I guarantee that this function will not exit until after the server call has been completed? Or, how can I guarantee that who ever is calling this function will get a true/false and not an undefined?
NOTE:
I've seen people use async: false but that hangs the UI which I do not want.
See http://api.jquery.com/jQuery.ajax/. You need to do an AJAX request with async: true to your parameters. You will then need to edit your code so the code that executes after a successful request is inside the successful block.