javascript function return problem

Marco Gasi
Marco Gasi used Ask the Experts™
on
Hi all.
I have a probably stupid problem I can' sove by myself :-(
I have this function which returns a number:
function getFolderCardsNumber(folder) {
	jQuery.ajax({
		type: 'post',
		url: 'script.php',
		data: {folder: folder},
		success: function (result)
		{
			var response = JSON.parse(result);
			console.log('in folder ' + folder + ' there are '+response + ' cards');
			return response;
		},
		error: function (result)
		{
			console.log('error');
		}
	});
}

Open in new window

The value in console is correct, so it looks to work fine. But here  I get undefined!
jQuery(document).ready(function ()
{
	var pc_cards_number, sp_cards_number;
	pc_cards_number = getFolderCardsNumber('PC');
	console.log('inner PC is '+pc_cards_number);
	sp_cards_number = getFolderCardsNumber('SP');
	console.log('inner SP is '+sp_cards_number);
});

Open in new window

Thnk you so mutch.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Sounds like this is doing access cross sites, e.g. another domain, port, ...
This is not allowed in browsers, when not specifically allowed by the server (see CORS)
Marco GasiFreelancer
Top Expert 2010

Author

Commented:
Hi Steh. Thank you for your reply, but that's not the case: the script is in the same domain
Marco GasiFreelancer
Top Expert 2010

Author

Commented:
In addition, notice that the function returns correct values and prints them in console. It's only from the code which calls the function that values are undefined...
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Marco GasiFreelancer
Top Expert 2010

Author

Commented:
The same result trying this:
jQuery('body').click(function(){
	pc_cards_number = getFolderCardsNumber('PC');
	sp_cards_number = getFolderCardsNumber('SP');
	console.log(pc_cards_number);
	console.log(sp_cards_number);
});

Open in new window

I thought I had to wait for all other script execution end but that has nothing to do with this: page completely loaded, in console appear the two output produced internally by the funciton itself; if I click I get right result from within the function and undefined by the click event. Going crazy, here...
Marco GasiFreelancer
Top Expert 2010

Author

Commented:
It looks like the click event calls the console.log() function before the function return the result...
Marco GasiFreelancer
Top Expert 2010

Author

Commented:
I even tried to set a timeout this way, in order to delay the console.log() call:
jQuery('body').click(function(){
	pc_cards_number = getFolderCardsNumber('PC', 
 	    setTimeout(function(){
		   console.log(pc_cards_number);	
            }, 1000)
	);
	sp_cards_number = getFolderCardsNumber('SP', 
	    setTimeout(function(){
	           console.log(sp_cards_number);	
	    }, 1000)
     );
});

Open in new window

Now the undefined are printed after the function has printed correct values... But they are still undefined!
Commented:
To me this sounds like the code is executing before an asyncronous call is completed. If so, consider using promises to handle the delay due to async code.

excuse the brevitiy, im on a mobile device.
Marco GasiFreelancer
Top Expert 2010

Author

Commented:
Thank you Gregg. Yes, now I agree about that. Please, when you are on a computer can you give some guidance on promises? In the meanwhile I'll investigate by myself :-) Cheers
Pravin AsarPrincipal Systems Engineer
Top Expert 2005

Commented:
Another possibility is conflict (same variable name in local (within function) and global (with your page)

You may do explicit declaration in global (page scope).
Marco GasiFreelancer
Top Expert 2010

Author

Commented:
Hi Pravin, thenk you for your reply but that is not the case. I learned soemthing about promises but... I can't test it now because the server has become suddenly unaccessible :-) Hope to work on tomorrow.
Cheers
Alexandre SimõesManager / Solutions Architect

Commented:
Hi Marco,
your problem is due to the fact that the ajax call is asynchronous and the function exits before the result arrives.

To solve this you have two options, either pass a callback or use promises.

I'll post here the callback example because is the easiest to understand:
function getFolderCardsNumber(folder, callback) {
  jQuery.ajax({
    type: 'post',
    url: 'script.php',
    data: {
      folder: folder
    },
    success: function(result) {
      var response = JSON.parse(result);
      console.log('in folder ' + folder + ' there are ' + response + ' cards');
      
      // call the callback function passing the result
      if(callback){
      	callback(response);
      }
    },
    error: function(result) {
      console.log('error');
    }
  });
}


jQuery(document).ready(function() {
  var pc_cards_number, sp_cards_number;
  
  getFolderCardsNumber('PC', function(result){
  	pc_cards_number = result;
  	console.log('inner PC is ' + pc_cards_number);
  });
  
  getFolderCardsNumber('SP', function(result){
  	sp_cards_number = result;
  	console.log('inner SP is ' + sp_cards_number);
  });
});

Open in new window

There's also the option to make the ajax call synchronous but I don't like to advise this because it will block the flow while the data is being fetched; resulting in a page hanging for the user.
Marco GasiFreelancer
Top Expert 2010

Author

Commented:
Hi Alexandre, thanks for your reply. But the use of callback let me uncertain: for the moment I just have to put the returned value in a variable...

@Gregg: I tried to use promises and things seems to go better, but not clearly enough to me :-)
function getFolderCardsNumber(folder) {
	return Promise.resolve(jQuery.ajax({
		type: 'post',
		url: 'script.php',
		data: {folder: folder},
		success: function (result)
		{
			var response = JSON.parse(result);
			console.log(folder+' is '+response);
			return response;
		},
		error: function (result)
		{
			console.log('error');
		}
	})
	);
}

jQuery(document).ready(function ()
{
	var pc_cards_number, sp_cards_number;
	getLinkRequests('new_link_requests');
	
	var promise = getFolderCardsNumber('PC');
	promise.then(function(result){
		pc_cards_number = result;
		console.log('inner 1 is '+pc_cards_number);
	});
	console.log('inner 2 is  '+pc_cards_number);
	var promise = getFolderCardsNumber('SP');
	promise.then(function(result){
		sp_cards_number = result;
		console.log('inner 3 is  '+sp_cards_number);
	});
	console.log('inner 4 is '+sp_cards_number);
});

Open in new window

The output is:

inner 2 is undefined
inner 4 is undefined
PC is 10 //printed internally by getFolderCardsNumber() function
inner 1 is 10
SP is 5 //printed internally by getFolderCardsNumber() function
inner 3 is 5

So it seems that I can't get a persistent value for my variables, that is a value which stays in variables outside some function. Probably this would be the result using Alexandre's suggestion using a callback function to printout values.

Probably, I can be happy with this solution (I have still to test in complete script) but I wouldlike to know what I'm missing here...
Manager / Solutions Architect
Commented:
Hi Alexandre, thanks for your reply. But the use of callback let me uncertain: for the moment I just have to put the returned value in a variable...
But that's how asynchronous ajax calls work.
Your function will exit before the ajax call finishes so the result will always be undefined.

If you want a quick and dirty fix, make your ajax call synchronous:
	jQuery.ajax({
		type: 'post',
                async: false,
		url: 'script.php',
		data: {folder: folder},
		success: function (result)
		{
			var response = JSON.parse(result);
			console.log('in folder ' + folder + ' there are '+response + ' cards');
			return response;
		},
		error: function (result)
		{
			console.log('error');
		}
	});

Open in new window

The promises approach is very similar in esence to the call back, but you put the logic in a different place.
You can, for instance, return the ajax call result, that is a jquery promise.
function getFolderCardsNumber(folder) {
  return jQuery.ajax({
    type: 'post',
    url: 'script.php',
    data: {
      folder: folder
    },
  });
}

Open in new window

And in this case you would have to use it like:
  getFolderCardsNumber('PC')
    .success(function(result) {
      var response = JSON.parse(result);
      pc_cards_number = response;
    })
    .error(function(result) {
      console.log('error');
    });

Open in new window

There's no magic here man... sorry :)
Marco GasiFreelancer
Top Expert 2010

Author

Commented:
I'll post link to a new quesiton soon. Thank you!
Marco GasiFreelancer
Top Expert 2010

Author

Commented:

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial