javascript function return problem

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.
LVL 32
Marco GasiFreelancerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Member_2_1001466Commented:
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 GasiFreelancerAuthor Commented:
Hi Steh. Thank you for your reply, but that's not the case: the script is in the same domain
Marco GasiFreelancerAuthor 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...
Your Guide to Achieving IT Business Success

The IT Service Excellence Tool Kit has best practices to keep your clients happy and business booming. Inside, you’ll find everything you need to increase client satisfaction and retention, become more competitive, and increase your overall success.

Marco GasiFreelancerAuthor 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 GasiFreelancerAuthor Commented:
It looks like the click event calls the console.log() function before the function return the result...
Marco GasiFreelancerAuthor 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!
GreggCommented:
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 GasiFreelancerAuthor 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 EngineerCommented:
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 GasiFreelancerAuthor 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 ArchitectCommented:
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 GasiFreelancerAuthor 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...
Alexandre SimõesManager / Solutions ArchitectCommented:
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 :)

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Marco GasiFreelancerAuthor Commented:
I'll post link to a new quesiton soon. Thank you!
Marco GasiFreelancerAuthor Commented:
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
JavaScript

From novice to tech pro — start learning today.