this is what I have:
function loadGraphs(datawijk){
$.ajax({
url: './api5.php', //the script to call to get data
data: {
wijk: datawijk,
}, //you can insert url argumnets here to pass to api.php
//for example "id=5&parent=6"
dataType: 'json', //data format
success: function(rows) //on recieve of reply
{
var htmlContent = "";
// ADD TO
htmlContent += '<tr><th scope="row">Geboortes</th>';
$.each(rows, function(i, data) {
$.each(data, function(j, year) {
htmlContent +=
'<td>' + year + '</td>';
});
});
htmlContent += '</tr>';
var lol = updateOverlijdens(datawijk, htmlContent);
alert(lol);
$('#graphs table tbody').html(htmlContent);
}
});
}
function updateOverlijdens(datawijk, htmlContent){
$.ajax({
url: './api4.php', //the script to call to get data
data: {
wijk: datawijk,
}, //you can insert url argumnets here to pass to api.php
//for example "id=5&parent=6"
dataType: 'json', //data format
success: function(rows) //on recieve of reply
{
// ADD TO
htmlContent += '<tr><th scope="row">Overlijdens</th>';
$.each(rows, function(i, data) {
$.each(data, function(j, year) {
htmlContent +=
'<td>' + year + '</td>';
});
});
htmlContent += '</tr>';
return htmlContent;
}
});
}
When I do alert(lol); in function loadGraphs I get undefined …
And when I do alert(htmlContent); in function updateOverlijdens just before I return the value I get it right. Only when I alert the value in my function loadGraphs I get undefined. How can I fix this?
As explained by a lot of answers, the problem is that you’re trying to return something from the AJAX call back to the function which initiated the call. This cannot work, since the caller does not wait for the AJAX call to complete and will return before it is completed. That’s the whole idea about asynchronous calls: you don’t want to block the execution to wait for the results to come in.
One way to handle this is by passing a callback function which needs to be executed when the results are retrieved. This function will then be called from within the AJAX success callback.
Another interesting approach is to make use of jQuery’s deferreds and promises. A promise represents some value which will be retrieved somewhere in the future. A deferred produces a promise and resolves it later on. For example, all AJAX functions return a promise and you can retrieve a promise from any jQuery object which is resolved when all animations are completed.
In your case, you can create a deferred which is resolved with the
htmlContentwhen the AJAX results are retrieved. You return the promise of that deferred from the function so the caller can bind callbacks to it or combine it with other promises.BEGIN EDIT
Thanks to Benjamin Gruenbaum for pointing out my usage of the deferred anti-pattern. Here’s an implementation using
.thento do the chaining:END EDIT
You can then use the promise in your
loadGraphsAJAX success callback like so:The advantage of using promises is that they give caller much more flexibility. The caller can easily register multiple callbacks using
then(), combine it with other promises usingjQuery.when()or pipe the results to another promise usingpipe()then.