1

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?

asked Jan 20, 2013 at 14:41
4
  • You forgot to post the code for "updateOverlijdens". Commented Jan 20, 2013 at 14:42
  • Ajax is still asynchronos Commented Jan 20, 2013 at 14:45
  • @MattiasBuelens ha ha durrr... I need some coffee Commented Jan 20, 2013 at 14:45
  • possible duplicate of How to return the response from an AJAX call? Commented Jul 30, 2013 at 15:38

3 Answers 3

4

The reason you are getting undefined is that you are not returning anything from updateOverlijdens (but from the inner function in success)

You are running asynchronous code, generally you can't solve this problem easily using the current function return pattern you are using since the data will not be available at the time of the return. What you need are callbacks.

Please see this page for good usage examples of jQuery ajax. What you'll be wanting to do is pass a function to updateOverlijdens and call it when the success callback of your ajax fires. There are plenty of examples for that online (and in the link above).

Here for example is your code after being modified to the correct callback pattern which addresses the problem it had with asyncrhonous execution

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>';
 updateOverlijdens(datawijk, htmlContent,function(lol){
 alert(lol);
 $('#graphs table tbody').html(lol);
 });
 } 
 });
}
function updateOverlijdens(datawijk, htmlContent,callback){
 $.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>';
 callback(htmlContent)
 } 
 });
}
answered Jan 20, 2013 at 14:43
Sign up to request clarification or add additional context in comments.

2 Comments

In this case, you can easily create and pass a callback to do $('#graphs table tbody').html(htmlContent);. Then, instead of returning htmlContent in updateOverlijdends, call the passed callback with htmlContent as argument.
To down voter, may I ask what you did not want find satisfactory?
1

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 htmlContent when 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.

function updateOverlijdens(datawijk) {
 // Create the deferred
 var dfd = new jQuery.Deferred();
 // Initiate the AJAX request
 $.ajax({ 
 url: './api4.php',
 data: {
 wijk: datawijk,
 },
 dataType: 'json',
 success: function(rows) {
 var htmlContent = '<tr><th scope="row">Overlijdens</th>';
 $.each(rows, function(i, data) {
 $.each(data, function(j, year) {
 htmlContent += '<td>' + year + '</td>';
 });
 });
 htmlContent += '</tr>';
 // Resolve the deferred
 dfd.resolve(htmlContent);
 },
 error: function() {
 // An error occurred, reject the deferred
 dfd.reject();
 }
 });
 // Return a promise
 return dfd.promise();
}

BEGIN EDIT

Thanks to Benjamin Gruenbaum for pointing out my usage of the deferred anti-pattern. Here's an implementation using .then to do the chaining:

function updateOverlijdens(datawijk) {
 return $.ajax({ 
 url: './api4.php',
 data: {
 wijk: datawijk,
 },
 dataType: 'json'
 }).then(function(rows) {
 var 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;
 });
}

END EDIT

You can then use the promise in your loadGraphs AJAX success callback like so:

// Produce the table header
var htmlContent = '<tr><th scope="row">Geboortes</th>';
$.each(rows, function(i, data) {
 $.each(data, function(j, year) {
 htmlContent += '<td>' + year + '</td>';
 });
});
var promise = updateOverlijdens(datawijk);
promise.then(function(htmlOverlijdens) {
 // Append to the previously created HTML content
 htmlContent += htmlOverlijdens;
 // Apply the HTML
 $('#graphs table tbody').html(htmlContent);
});

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 using jQuery.when() or pipe the results to another promise using (削除) pipe() (削除ここまで) then.

answered Jan 20, 2013 at 15:07

1 Comment

Hi, I now understand promises a lot better than I used to. Please consider replacing your deferred anti pattern with proper .then calls. Thanks. i.e. return $.ajax(...).then(function(rows){... return...})
0

Yes. There no mistake. You need to have return value for your function definied not in $.ajax. In your code you returning value to $.ajax, not to updateOverlijdens. Right code need to be:

function updateOverlijdens(datawijk, htmlContent){ 
 $.ajax({ ....}) 
 return 'some value' 
}
answered Jan 20, 2013 at 14:46

3 Comments

The real problem is that the OP wants to return a value retrieved in the AJAX call.
Yes indeed, I need the value in the ajax call
Then do your alert after ajax callback - alert(htmlContent)

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.