Global variables in Javascript not updating - javascript

I have spent the last 30 mins figuring this out.
Let's assume the following case:
<script>
var x = 0 ; //global variable
function compute() {
x = x+1;
}
</script>
Should the value of x be incremented so I can access it into a function later on?
I have the following codes:
var id1 = 0;
var id2 = 0;
$.ajax({
url: "http://localhost/twee/chat/comment",
type: 'POST',
data: form_data,
success: function(data) {
var data1 = parseInt(data);
id1 = id2 = data1;
}
});
I want to be able to access the values of id1 and id2 (updated since i declared them as 0) in a later function.
However, the value is staying zero and data1 is retrieved just fine.

I dont know when you try to use the ID's, but the ajax call is asynchronus, so if you try to read the variables like this:
var id1 = 0;
var id3 = 0 ;
$.ajax({
url: "http://localhost/twee/chat/comment",
type: 'POST',
data: form_data,
success: function(data) {
var data1 = parseInt(data, 10);
id1 = id2 = data1;
alert(id1) // Will alert whatever number returned as data.
}});
alert(id1) // Will alert 0
The second alert will be called almost simultaneously with the ajax call, and at that point the data has not been updated yet, while the first alert will not be called until the data has returned. If you are going to use the ID's, you will have to use them within your success-callback, or in a function that is called within your success-callback.

Are you sure that you're checking the value of id1 after the success callback runs? ajax is an asynchronous operation, your callback won't be called until the response comes back from the server.

Your ajax callback is asynchronous. It won't run the success function until after the remote server responds. Once it does, your function is executed, and the variable is incremented.
This is a difficulty in Javascript programming, and asynchronous programming in general: there are a number of balls in the air at once, and it is difficult to reason about how they might complete their operations, and when you can see the results.
It's very easy to think of the $.ajax() call as "get the results from the server," but it's really, "make a request to the server." Who knows when it might finish?

Related

I can't seem to break out of A $.each() loop

I can't seem to manage to break out of my each loop if the ajax returns an error. I've tried
return false;
and other similar thing but the $.each still continues to run.
I need to be able to do this so that I can display error messages from my back end after posting it via ajax(I know this is bad practice however a client needed to be able to be able to send multiple forms off at once.).
Can anyone explain what I've done wrong?
var postAll = function(button_clicked)
{
e.preventDefault();
var form_response = [];
var formsCollection = document.getElementsByTagName("form");
$.each(formsCollection, function (key, value)
{
console.log(value.action);
console.log(value.id);
var url = value.action;
var id = value.id;
var data = ($('#' + id + '').serialize());
if (id == 'additionalInfo')
{
data = {'Add_info': $('#Add_info').val(),};
}
if (id != 'DONE')
{
$.ajax({
type: "POST",
dataType: 'json',
url: url,
beforeSend: function (xhr)
{
xhr.setRequestHeader('X-CSRF-TOKEN',$("#token").attr('content'));
},
data: data,
success: function (data)
{
console.log('success'); // show response from the php script.
form_response.push(data); // show response from the php script.
},
error: function (data)
{
console.log('fail'); // show response from the php script.
display_errors(data, id); // show response from the php script.
return true;
}
});
}
});
}
AJAX is asynchronous, when executing your $.each function it will execute the AJAX call and "Not wait" for the others to finish
To solve your problem you'll have to write a function that will execute the first ajax call and in the success it will execute itself again with the second ajax call.
Example:
var data = [form1,form2...etc];
function letsLoop(data,index = 0){
$.ajax({
url:....
success: function(){
letsLoop(data,index+1);
},
error: function(){
}
});
}
and here you call your function:
letsLoop(data,0);
If by breaking out of the loop you mean the return in your error handler, then it won't work as you think it would.
Your loop creates asynchronous requests 'at once'. Then each of these requests is handled by the browser (more or less simultaneously), then come responses. So by the time your error handler runs the loop has long finished.
BTW, the return in your case relates to the error handler, not the function inside the loop.
So, to achieve what you want you should 'queue' your AJAX requests and perform them one by one.
One possible solution is to create an array of forms then take (and remove it from the array) the first one, perform a request, on a response repeat the whole thing, and keep repeating until the array is empty.

Confused with javascript global variable scope and update

I am trying to get a specific piece of data from from a json source. I have declared a global variable and try to update the global variable but it doesn't update correctly. Also, the order in which my debug alerts run is confusing.
<script>
//global variable
var latestDoorStatus = "initialized value"; //set value for debugging purposes
//debug alert which also calls the function
alert("Alert#1: call getDoorStatus = " + getDoorStatus("***********"));
function getDoorStatus(public_key) {
//get data in json form
var cloud_url = 'https://data.sparkfun.com/output/';
// JSONP request
var jsonData = $.ajax({
url: cloud_url + public_key + '.json',
data: {page: 1},
dataType: 'jsonp',
}).done(function (results) {
var latest = results[0];
//debug alert
alert("Alert #2: latestDoorStatus = " + latestDoorStatus);
//update the global variable
latestDoorStatus = latest.doorstatus;
//debug alert
alert("Alert #3: latestDoorStatus = " + latestDoorStatus);
//return the global variable
return latestDoorStatus;
});
alert("Alert #4: latestDoorStatus = " + latestDoorStatus);
}
</script>
When I run this in my browser I get the following behaviors:
First I get alert#4 (supposed to run at END of the script) with the initialized value of the global variable
then I get alert#1 as "undefined". This is supposed to be the result of calling the function getDoorStatus which should return an updated value of latestDoorStatus
then I get alert #2 as the initialized value of latestDoorStatus which makes sense since the global variable has not yet been updated
then I get alert #3 with the correct value of latestDoorStatus
The function is supposed to return the variable latestDoorStatus AFTER alert #3 (i.e. after global variable has been updated correctly) so I don't understand why alert #1 (which is supposed to have the returned value) is coming back undefined and why alert#4 which is supposed to run at the very end of the script is running first.
You are calling $.ajax asynchronously, and passing a callback function to done.
function makeRequest() {
$.ajax({ // An async Ajax call.
url: cloud_url + public_key + '.json',
data: {page: 1},
dataType: 'jsonp',
}).done(function (results) {
// this code is executed only after the request to cloud_url is finished.
console.log("I print second.");
});
console.log("I print first.");
}
The callback is called when the request is finished, and when depends entirely on how long the request to https://data.sparkfun.com/output/ takes. So the code after your Ajax call is executed immediately, we're not waiting for the http request to finish.
Your function getDoorStatus returns nothing, but your callback passed to done does. The thing you need to know is that you can't return anything from asynchronously executed functions. Well, you can return, but there will be nothing there to use the returned value.
So instead, do the things you want to do with the returned data from https://data.sparkfun.com/output/ in the callback passed to done.
function getDoorStatus(public_key) {
//get data in json form
var cloud_url = 'https://data.sparkfun.com/output/';
// JSONP request
var jsonData = $.ajax({
url: cloud_url + public_key + '.json',
data: {page: 1},
dataType: 'jsonp',
}).done(function (results) {
// latestDoorStatus = results[0]; // Not a good practice.
// Instead:
showDoorStatus(results[0]);
});
}
function showDoorStatus(status) {
document.getElementById("door-status").innerText = status;
// Or something like this.
}
getDoorStatus("***********");
And somewhere in your HTML:
<p id="door-status"></p>
.done() will be called after the response of the AJAX request got received!
1) getDoorStatus() is called from inside alert() at top of code => #4 shown. It does not matter that the function is defined below and not above.
2) alert() at top of code is called & getDoorStatus() does not directly return a value => #1 shown with undefined.
3) AJAX response returned, .done() function gets called => #2 and #3 are shown.

multiple ajax async not in order and need synchronous behavior

Sorry, My first language is not English. I am not sure that if I explain my question properly.
My code is like a main function have two ajax functions (Use ajax function to get foursquare API)
main(){
ajax1();
ajax2();
all other codes
}
the ajax2() function has to get result from ajax1() as input and then return result(actually result was pushed in to global array).
all other codes should be processed after two ajax functions are finished. I tried the asyn: false but it is not working. My html file include newest jquery like this
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js" ></script>
I try the jquery function $.when().done() function and the first ajax works. However, the second ajax() function was in the for loop. The for loop will destroy the mechanism of $.when().done() function:
first ajax: in firstjson function
Second ajax: in transfer function
function firstjson(tmpName,tmpLoc,PhotoJson,foursq){
return $.ajax({
type: 'GET',
url: foursq,
dataType: 'jsonp',
success: function(json) {
for (i = 0; i < 3; i++) {
var resultname = json['response']['venues'][i].name;
var resultlocation = json['response']['venues'][i].location;
var resultlat = resultlocation.lat;
var resultlng = resultlocation.lng;
var tmpmarker = new google.maps.LatLng(resultlat,resultlng)
tmpName.push(resultname);
tmpLoc.push(tmpmarker);
var resultid = json['response']['venues'][i].id;
var tmpPhotoJason = 'https://api.foursquare.com/v2/venues/'+ resultid +'/photos?';
PhotoJson.push(tmpPhotoJason);
}
}
});
}
function transfer(PhotoJson,PhotoURL){
for (i = 0; i < 3; i++) {
return $.ajax({
type: 'GET',
url: PhotoJson[i],
dataType: 'jsonp',
success: function(json) {
resultphoto = json['response']['photos']['items'];
photoprefix = resultphoto[i].prefix;
photopresuffix = resultphoto[i].suffix;
photourl = photoprefix+"150x150" + photopresuffix;
PhotoURL.push(photourl);
}
});
}
}
$.when(firstjson(tmpName,tmpLoc,PhotoJson,foursq)).done(function(){
alert("test1");
$.when(transfer(PhotoJson,PhotoURL).done(function(){
console.log(PhotoURL);
all other codes!!!!
});
});
//PhotoURL is global array
So the first "when" function work properly. alert("test1") work after the firstjson was done. However the for loop inside transfer function will break the when function. How can I fix the problem. Please help me. I will appreciate you can give me any related information. Thanks!!!
This will execute ajax2 after ajax1
function anotherMethod(){
//Here you do all that you want to do after the last $ajax call
}
main(){
firstjson(tmpName,tmpLoc,PhotoJson,foursq)
.then(transfer(PhotoJson,PhotoURL))
.then(anotherMethod);
}
As you are returning a promise from the first with the "return $ajax..."
So you organice your code like this:
in methods with ajax calls you return the call as you are doing now
return $.ajax();
that returns a promise that you chain.
And you put what you want to do in another method so you call it in the last "then".
Non-Blocking Example
You should use non-blocking code. You can turn async off (async: false) but this can easily be done in a non-blocking manor using callback functions.
function main(){
$.ajax({ // First ajax call (ajax1)
url: "first/ajax/url",
type: "GET", // POST or GET
data: {}, // POST or GET data being passed to first URL
success: function(x){ // Callback when request is successfully returned
// x is your returned data
$.ajax({ // Second ajax call (ajax2)
url: "second/ajax/url",
type: "GET", // POST or GET
data: {
thatThing: x
}, // POST or GET data passed to second URL
success: function(y){
// y is your second returned data
// all other codes that use y should be here
}
});
}
})
}
This would be the non-blocking approach, nest your function within "success" callback functions. Nest ajax2 within ajax1's "success" callback to ensure that ajax2 is not executed before ajax1 has returned and nest your "all other codes" inside the "success" callback of ajax2 to ensure they are not executed until ajax2 has returned.
Blocking Example
If you absolutely must (please avoid at all cost) you can disable async which will block all JavaScript code from executing until the ajax has returned. This may cause your browser to temporarily freeze until the ajax request has returned (depending on the browser).
function main(){
var x = ajax1();
var y = ajax2(x);
window["y"] = y; // push to global as you requested but why?
// All other codes that can now use y
}
function ajax1(){
var x;
$.ajax({
url: "first/ajax/url",
async: false,
type: "GET", // POST or GET,
data: {}, // POST or GET data being passed to first URL
success: function(r){x=r}
});
return x;
}
function ajax2(x){
var y;
$.ajax({
url: "second/ajax/url",
async: false,
type: "GET", // POST or GET,
data: {
thatThing: x
}, // POST or GET data being passed to second URL
success: function(r){y=r}
});
return y;
}
Once again I stress, try not to disable async that will cause your code to block and is BAD code. If you absolutely 100% have to for some reason than than it can be done but you should attempt to learn how to write non-blocking code using callbacks as the first example does.
Social Network Example
Now I'll do an example of an ajax call to get an array of your friends IDs, and then a series of ajax calls to get each of your friends profiles. The first ajax will get the list, the second will get their profiles and store then, and then when all profiles have been retrieved some other code can be ran.
For this example, the url https://api.site.com/{userID}/friends/ retrieves an Object with a list of friends IDs for a particular user, and https://api.site.com/{userID}/profile/ gets any users profile.
Obviously this is a simplified api as you will probably need to first establish a connection with a apikey and get a token for this connection and the token would likely need to be passed to the api uris but I think it should still illustrate the point.
function getFriends(userID, callback){
$.ajax({
url: "https://api.site.com/"+userID+"/friends/",
success: function(x){
var counter = 0;
var profiles = [];
for(var i=0;i<x.friendIDs.length;i++){
$.ajax({
url: "https://api.site.com/"+x.friendIDs[i]+"/profile/",
success: function(profile){
profiles.push(profile);
counter++;
if(counter == x.friendIDs.length) callback(profiles);
}
});
}
}
});
}
getFreinds("dustinpoissant", function(friends){
// Do stuff with the 'friends' array here
})
This example is "Non-blocking", if this example were done in a "blocking" way then we would ask for 1 friends profile, then wait for its response, then request the next and wait and so on. If we had hundreds of friends you can see how this would take a very long time for all ajax calls to complete. In this example, which is non-blocking, all requests for profiles are made at the same time (within 1ms) and then can all be returned at almost exactly the same time and a counter is used to see if we have gotten responses from all the requests. This is way way way faster than using the blocking method especially if you have lots of friends.

Javascript value is returned from webservice but will not show unless a breakpoint is used

I have a javascript function that calls a web service. The data comeback (I see the Jason return in FireBug) the value is blank when I attempt to use it unless I set a break point. With a break point set the value can be used, without it is not available.
Here is a snippet of the offending call.
function getTheNote(noteCode){
var _myNote = "";
var theID = $('#CustNo').val();
var myDTO = { 'theID': theID, 'noteCode': noteCode, };
var toPass = JSON.stringify(myDTO);
$.ajax({
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: "json",
url: "AR_Cust_Mgt.aspx/getNote",
data: toPass,
success: function (data) {
_myNote = data.d;
}
});
//setTimeout(_myNote += _myNote, 120000);
//for(var x = 0; x < 200000; x++){}
//return _myNote;
alert(_myNote);
}
Originally I was sending the value back to a calling function the return statement is where I would set my break point and the data would be returned, without nothing. Now you can see I attempted to use an alert inside the function with the same results.
With a break point I get a value without I get nothing, I have even attempted to use some delays.
Please help.
The ajax call is asynchronous. Anything you want to do with the result needs to be in your anonymous function success: function(data) { ... or the anonymous function needs to call other functions to do stuff.
As it is coded now, $.ajax will be called, the script execution continues on before the ajax call returns.
small change, big difference: you are not calling alert IN the succes function
success: function (data) {
_myNote = data.d;
alert(_myNote);
}

JavaScript auto-incrementing a variable in jQuery and AJAX

I have JavaScript using jQuery and AJAX which creates a dynamic array, which has some values used for AJAX request as below;
<script type="text/javascript">
var array = Array("y","y","x","y","y","y");
function updateBackground(cellId, titleId) {
var i = 0;
$.ajax({
type: "POST",
url: "ajax.php",
data: {
filename: Array(array[i], "testdata", $("#"+titleId).html())
},
success: function(response){
$("#"+cellId).css("background-image", "url('pdfthumb/" + response + "')");
}
});
i++;
}
</script>
The script is suppose to submit values in the array in array[i] for each AJAX request. I made a variable var i which auto increments.. But the script is not working.. The script works well if array[i] is replaced by array[0] or array[1] etc..
How can I solve the syntax error?
Every time you call updateBackground() i = 0 (again). May be you must initialize i outside of the function.
What happens if i > array.length? And I would rename the variable.
You don't have an iterator. Your variable i gets set to 0 every time the function runs. The increment at the end is useless.
Maybe you need something like this?
var array = Array("y","y","x","y","y","y");
function updateBackground(cellId, titleId) {
for( var i = 0; i < array.length; i++ ) {
$.ajax({
type: "POST",
url: "ajax.php",
data: {
filename: Array(array[i], "<?php echo $dir; ?>", $("#"+titleId).html())
},
success: function(response){
$("#"+cellId).css("background-image", "url('pdfthumb/" + response + "')");
}
});
}
}
Each time you call updateBackground() function, the i variable is being reinitialized. It's just a local variable and as soon as the function finishes it's being destroyed by GC. You could do something like this:
var UpdateBackground = {
array: [..],
counter: 0,
doUpdate: function(cellId, titleId) {
// AJAX request
this.counter++;
}
};
UpdateBackground.doUpdate(1, 1);
UpdateBackground.doUpdate(1, 1);
I think that you should send the whole array maybe as a commaseparated string and instead and make just one ajax request, because http-requests are expensive and change the server side code accordingly. And fetch the cellids as an array.
If you think that you have a long list or a table it can be like a lot of requests. Do the stuff in client code and do the stuff in server code and keep the number of http-requests as few as possible.
And use the join method on the array.
var arr = [ 'y', 'y' ];
arr.join(',');
// outputs y, y
I fixed it... Thank you so much #Jed, #Pointy, #Crozin, and #Lord Vader for helping me to figure it out.... :)
I just take var i = 0; outside the loop.... above var array like;
var i = 0;
var array = Array("y","y","x","y","y","x");

Categories

Resources