Variables inside nested anonymous functions in javascript - javascript

Can someone one explain it please?
Why alert 2 pops before alert 1?
Why value of pageCount in alert 1 is different than alert 2?
function naviSet()
{
var pageCount;
if($.ajax({
type: "POST",
url: "http://localhost/mywebsite/wp-content/themes/twentyeleven/more-projects.php",
success:function(data)
{
pageCount = data;
alert(pageCount); //alert 1
return true;
},
error:function()
{
$("#direction").html("Unable to load projects").show();
return false;
}
})) alert(pageCount); //alert 2
}

The alert1 is inside a callback - this function will only be called when the ajax request completes successfully (ie asynchronously).
The pageCount is different for the same reason - the success callback has not been made when alert2 is called.

As most answers mention you make an asynchronous call, but thats not really the reason. So JavaScript is single threaded, only on think can be done per time.
So first you call your function and this function will put on the execution context stack. This function will be executed before any other function that will be added to stack can be executed. In this function you make your ajax call and on success the success function will be put on the execution context stack. So this function could never ever called before naviSet. As alert1 is made in the naviSet function it will be the called first.
And to your second question:
From your function I think you believe, when $.ajax() returns true, your ajax call was succesful and pageCount was set to data. But it isn't. $.ajax doesn't return true but the truethy value $. Its a function that return reference to the main jquery object, so you can chain function calls.
function naviSet()
{
//you create a new var which is undefined
var pageCount;
// return $ which is a truethy in JavaScript, but it does not mean the ajax call was successful
if($.ajax({
type: "POST",
url: "http://localhost/mywebsite/wp-content/themes/twentyeleven/more-projects.php",
success:function(data)
{
// now you in the context of your success function
// and set the value of your variable to data
pageCount = data;
alert(pageCount); //alert 1
return true;
},
error:function()
{
$("#direction").html("Unable to load projects").show();
return false;
}
}))
//here you are still in the context of your naviSet function where pageCount is undefined
alert(pageCount); //alert 2
}

Why alert 2 pops before alert 1?
Alert 1 is fired by the callback function that is fired when a successful HTTP response has been received.
Alert 2 fires as soon as the HTTP request has been sent.
Networks are slow.
Why value of pageCount in alert 1 is different than alert 2?
Because it is changed when the response has been received (just before it is alerted), by the same callback function as mentioned above.

The ajax-function retrieves data from the given url asynchronously. That means that it is doing it in the background, while the rest of your code executes. As soon as it is finished, the function assigned to "success" is called (or "error", if it fails).
The second alert is called first because of this. Like I said, the rest of the code continues execution while the ajax-function is working.

The reason the second alert happens first is because the ajax call is asynchronous. It essentially schedules a web call and returns immediately. Hence the line after it which is the second alert happens directly after.
At some point later in time the web request will complete and call into the success function. Hence the first alert happens at that point

Related

javascript global variable not updating in ajax callback

On alert it always alerts jojo. The test2.php have text Loco
The div gets updated to Loco but the global variable is not changing. I tried window.temp = data but it didn't worked.
How can i get the returned value in variable? please Guide...
<div>
yolo
</div>
<script type="text/javascript">
var temp = 'jojo';
$.ajax({
url: 'test2.php', //Loco
success: function(data)
{
temp = data;
$('div').html(data);
},
error: function (err)
{
alert('error');
}
});
alert(temp);
var toBeUsedLater = temp; //updated temp value from ajax call
refreshTab();
</script>
This is an asynchronous function. (That's what the A in AJAX stands for.) You are alerting the value of temp immediately , so it is happening before the asynchronous call has finished. If you add
alert(temp);
To the end of your success handler, you will see the value has updated.
AJAX - asynchronous means you are not waiting for response to come and Javascript is interpreted language executed one line after another line. So here the alert(temp) would be executed first and then the success callback as it takes some time to get the response.
1)change
var temp = 'jojo'
to
'temp = 'jojo'
As this is not tied down to the execution context and not limited to files (has pluses and minuses - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
2) The problem is that the alert is called before the callback.
Move the alert into the function. As the ajax is called asynchronously, meaning the success and error functions are called, only when the ajax gets the response back from the server, while the alert you have now will be called right away.
http://javascript.about.com/od/ajax/a/ajaxasyn.htm
$.ajax({
url: 'test2.php', //Loco
success: function(data)
{
temp = data;
$('div').html(data);
alert(temp).
},
error: function (err)
{
alert('error');
}
});
3) alternatively you could set the async of the ajax to false:
What does "async: false" do in jQuery.ajax()?
Which will cause the Ajax call will finish before the next line of code, but it is highly recommended not to do that.
Just add async: false in your ajax options.

Global variables in jQuery plugin

I am creating a jquery plugin. In that am using some global variablse
$.rmtableparams.recordsCount: 0 is one of them.
I am assigned some values to this from one function inside an ajax call.
callAjax = function (surl, pselector, pi, rec) {
$.ajax({
..
success: function (data) {
$.rmtableparams.recordsCount =10;
}
});
}
But while I am trying to access $.rmtableparams.recordsCount in some other function it returns 0. But strange thing is that if i alert anything before that it will returns 10 correctly.
Ie: if my script is
alert("hi");
alert($.rmtableparams.recordsCount);
the second alert will shows 10
But if only alert($.rmtableparams.recordsCount); is there it returns 0
I was wondered with this. If any body knows the reason please help me.
The assignment $.rmtableparams.recordsCount =10; is inside the success callback of an $.ajax request. So the value isn't assigned until the ajax call is completed, and a response received. This happens fairly quickly, so while you're first alert is waiting to be closed, the ajax response is received, and the assignment is processed. Then, the second alert shows the new value.
If you leave out the first alert, the call is still being processed and the $.rmtableparams.recordsCount value hasn't changed yet.
It's as simple as that: AJAX stands for Asynchronous JavaScript And XML. Async is key, but often overlooked...
You can't just go ahead and set $.rmtableparams.recordsCount because $.rmtableparams doesn't exist.
You first need to set $.rmtableparams:
$.rmtableparams = {};
Then you go ahead and add data to the object:
$.rmtableparams.recordsCount = 10;
Make sure that the success callback is being fired. Add an alert or console.log inside the callback to do the check.

How to make function that returns it's inner-function's value?

It's probably obvious to you, but I can't figure it out.
I need to make function that returns it's inner-function's value. In other words, I have function get_users() that must return JSON object. That JSON object is got by $.post (built-in jQuery).
function get_users() {
return
$.post(
url_base + 'travel/trip/get_users/' + trip_id,
function(response) {
return response;
},
'json'
);
}
(above is what I tried to do, but it returned undefined - what a surprise)
Because of variable scope, I cannot just make variable in inner-function because it won't be visible in main function. I don't want to use global variables neither. Looking for better solution!
Thanks in any advice!
Why are you fighting against the asynchronous nature of AJAX? When you do AJAX you should get accustomed to work with events and callbacks instead of writing sequential code. You can't return the inner contents. The simple reason for this is that this inner function could execute much later than the outer function. So the outer function will return a result much before the success callback executes.
So here's the correct way:
function get_users() {
$.post(
url_base + 'travel/trip/get_users/' + trip_id,
function(response) {
// instead of trying to return anything here
// simply do something with the response
// Depending on what the server sent you there
// will be different ways.
// Here you could also call some other custom function
// and pass it the response
}
'json'
);
}
You can't return values from ajax calls. (Without setting async false, but that wouldn't really be ajax)
By the time you hit the inner return, the outer function has already completed
You will need to use a callback to process the users.
get_users(function(response) { // this anonymous function is passed in as a parameter
// do something with the response
});
function get_users(callback) {
$.post(
url_base + 'travel/trip/get_users/' + trip_id,
function(response) {
// call the passed in function and pass in the response as a parameter
callback(response);
},
json'
);
}
You need a primer on how asynchronous ajax calls work.
When you call $.post(), it starts a networking call to do the post and immediately returns from the $.post() call and continues executing the rest of your javascript. It will even exit your function get_users() right away.
But, the ajax call is not yet done - it's still in progress. Some time later, the ajax call will finish and when that happens the success handler for the ajax call that you have defined as function(response) {...} will get called. Only then, at that later time, is the response value from the ajax call known.
This is what asynchronous ajax means. You cannot write a call like get_users() and expect it to get the users and return with them. Instead, you have to make use of callback functions that will get called some time later (when the ajax has completed) and you can continue the path of your code then. Yes, this is inconvenient, but it's how things work in javascript with asynchronous ajax calls. The benefit of asynchronous ajax calls is that the browser and other javascript code can be fully live while the ajax call is underway. The cost of asynchronous ajax calls is that coding for them is more complicated.
You have a number of choices for how to deal with this complication. First off, you can make your get_users() call and then just continue the programming sequence that you want to carry out in the internal callback inside of get_users() since that's the only place that the response (the actual users) is known. If you're only using get_users() in one place in your code, then that could work fine. It would look like this:
function get_users() {
$.post(
url_base + 'travel/trip/get_users/' + trip_id,
function(response) {
// process the user list here and continue whatever other code you
// need that deals with the user list
},
'json'
);
}
If you need to use get_users() in several different places for different purposes, then you can change it to take a callback itself and let the post call just call that callback when the ajax call is done. You would then complete your processing of the response in that callback function:
function get_users(callback) {
$.post(
url_base + 'travel/trip/get_users/' + trip_id,
callback,
'json'
);
}
In this second option you could call get_users() like this:
get_users(function(response) {
// process the user list here and continue whatever other code you
// need that deals with the user list
});
There are even more advanced options available using jQuery's deferred object.

JavaScript variable reference problem

I'm trying to send a request and then in callback function, change the parameters and then send the request again. Something like this:
function sendRequest() {
params = {param1:'value', param2:'value'};
while(params) {
$.getJSON("url", params, function(data) {
if(data contains something important)
params.foo = bar;
else
params = null;
});
}
}
But params never changes and the while loop continues for ever. It seems to be a reference problem; but I can't figure out how to solve this. Thanks in advance.
The problem is that getJSON is asynchronous.
while(params) executes. It's truthy, so we continue
$.getJSON is called. The function passed to it will not be called at this time. It's just queued to the subsystem that later will perform the actual request - asynchronously.
while(params) executes again. The callback passed to getJSON has not gotten a chance to run yet, so params is unchanged.
Go to step 2.
In other words, you created an infinite loop, since the system that processes the queued callback function never gets to execute because of the infinite loop. All you end up doing is creating a infinitely long list of queued getJSON calls.
A better solution would be something like this:
function sendRequest(params) {
$.getJSON("url", params, function(data) {
if(data contains something important)
params.foo = bar;
sendRequest(params);
else
params = null;
// Probably do something like requestChainFinished(params);
});
}
sendRequest({param1:'value', param2:'value'});
By using a function, you take control of the flow and don't perform another request until the asynchronous callback to getJSON has been called.
'params' is a closure variable. The value of params changes at a later time in the callback when the asynchronous ajax call's response arrives, but your while loop is keeping the JS engine busy that the callback isn't going to get called ever.
Either you could keep calling the same function in the response callback or you can use async: false like this $.ajax({ async: false, ...

function with jquery ajax in it not returning value

This function wont return any value, even though the ajax call goes through correctly
Function:
function queryData(request)
{
var ret = null;
$.ajax({
url: 'ajax.php',
data: 'requestdata='+request,
dataType: 'json',
type: 'post',
success: function (j) {
if(j.ok == true)
return j.data;
else
return 'error';
}
});
return 'error';
}
The ajax function works asynchronously, meaning that it will execute the success function when it gets the result back from the server.
The queryData function will always return 'error' due to the nature of AJAX requests (at least performed this way). You can force the ajax requests to be done synchronously, but this is usually not the desired behavior.
You should add the logic that you want in your success function, rather than trying to return it back. You can pass a named function to the success option if you prefer that. See the jQuery documentation on ajax here.
You can't do that.
AJAX is asynchronous, meaning that your function will return before the server sends a response.
You need to pass the value using a callback, the way $.ajax does.
This function returns a value before the ajax call actually completes. An ajax call is an asynchronous operation, so when you do the $.ajax() call, it immediately returns, your function runs into the return 'error' on line 16 and returns 'error'.
A few milliseconds later the ajax call completes and your success function gets executed, but its return value is not going anywhere.
The success function will be called asynchronously. So first of all the function initialize the ajax request and ended with the last statement return 'error';. After that, after the receiving the response from the server the success function will be called from jQuery. It returns back to the jQuery but will not be used.

Categories