Question about JavaScript variable scope - javascript

Can someone tell me why this alert is empty?
var pending_dates = [];
$.getJSON('/ajax/event-json-output.php', function(data) {
$.each(data, function(key, val) {
pending_dates.push({'event_date' : val.event_date});
});
});
alert(pending_dates);
I can't get my head around this. Am I not declaring pending_dates as a global variable, accessible within the each loop? How would one solve this?
Please note that the JSON output is working well. If I would declare pending dates within the getJSON function (and alert within that function), it works, but I need to store the data in an array outside of that getJSON function.
Thanks for your contributions.
EDIT
Thanks to your comments this code is working:
pending_dates = [];
$.getJSON('/ajax/event-json-output.php', function(data) {
$.each(data, function(key, val) {
pending_dates.push({'event_date' : val.event_date});
});
}).success(function() { alert(pending_dates); })
Thanks a lot for your contributions!

I think the problem is $.getJSON is an asynchronous call - it returns immediately and then alert(pending_dates) is invoked.
However, when that happens, the response from the asynchronous call may not have been received, and hence pending_dates may not have been populated.
That is probably why it is empty at the time alert(pending_dates) is called.

Your alert is executing before the JSON call has finished. Remember this JSON it fetched and processed asynchronously, but your alert comes right after it's started. If you want an alert, then you need to put it at the completion of the getJSON call.

$.getJSON is working asynchronously meaning that whatever you have specified in the callback will be executed eventually but there is no guarantee that will happen by the time you reach alert('pending_dates').
You can verify this by moving alert('pending_dates') right after
pending_dates.push() (this would result in one alert being displayed for each item it is retrieving).
You can write a function to start working with the data you're retrieving as soon as it is available:
var pending_dates = [];
$.getJSON('/ajax/event-json-output.php', function(data) {
$.each(data, function(key, val) {
pending_dates.push({'event_date' : val.event_date});
doSomething(val.event_date);
});
});
function doSomething(date) {
// do something with date
// like writing it to the page
// or displaying an alert
}
With this you'll be able to work with all the data you get as it becomes available.

Variables are global by default in Javascript - having var actually introduces scope. Remove that and see if it helps.

It's more likely that the AJAX response isn't returning any data. Can you try pushing just 'foo' onto the array, and see if the alert shows anything different?

Related

Scope of global array javascript [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 5 years ago.
I am trying to load data from a csv and store it in an array of objects. I know global variables are frowned upon but I can't think of a better way to store the data and access it from multiple functions.
Here is my code:
var mydata = new Array;
$(document).ready( function () {
$.get('./datafile.csv', function(data) {
var head = data.split("\n");
for(var i = 1; i < head.length; i++){
line = head[i].split(",");
var obj = {
index:i,
img:line[0],
caption:line[1],
desc:line[2]
};
mydata.push(obj);
}
console.log(mydata); //1
});
console.log(mydata); //2
//I then want to select various elements on my page and set some attributes to
//an object in my data, but I can't since everything is undefined
});
At the first spot it logs my data correctly, but at second spot it logs an empty array. I read this article on global variables in JavaScript so I'm not sure what is going wrong.
The second part (//2) runs too soon. When $.get executes, it just starts the HTTP request to get the CSV, but doesn't wait for it to finish - that's why you need to pass that function(data) in. After the request finishes, the callback function gets called, and it's there that you should continue your initialization.
So, your code should look something like that below. (if you need to use the data elsewhere, you can keep on using the global, but it's not needed just for this)
$(document).ready( function () {
$.get('./datafile.csv', function(data) {
var mydata = [];
var head = data.split("\n");
// ...
console.log(mydata); //1
continueSetup(mydata); // 2
});
});
function continueSetup(mydata) {
// do what you need
}
I think you might be getting confused about the order of what is happening in your code. First of all, there is nothing wrong with using a global variable like this, especially if you are accessing it multiple times throughout your page (using events and such). Secondly, the reason you are seeing an empty array at your "second" spot in code is because that spot (#2) is actually getting executed before your get function has received the data and before #1.
get is an asynchronous function, which means that it waits to receive a response, and then executes the code inside (including #1). However, #2 gets executed immediately, while your array is still empty.
At 2 the data will be same as what you initialized. At 1 the data will be the same as what you populated.
2 gets printed first if you have observed closely. This is because $.get is an asynchronous call and gets executed in the background. The callback you are providing to $.get will run after the GET request is either successfully completed or errored out.

Can we save jquery POST/GET callback function's data and status in a variable for further use?

I want to save the value of data and status in a variable and use it after the closing brackets of jquery GET/POST function.But alert comes only when it is inside .get braces.
$(document).ready(function(){
$.get("demo_test.asp",function(data,status){
v = data;
});
alert("Data:"+v);
});
As Jasper said, your alert is being triggered before the request is complete (async!). So, you have two options:
Do your logic inside the callback:
$.get("demo_test.asp",function(data,status){
v = data;
alert("Data:"+v);
//Process stuff here
});
Or pass the received data onto another function and work with it there
$.get("demo_test.asp",function(data,status){
v = data;
doStuff(v);
});
function doStuff(param) {
console.log(param);
}
You're absolutely correct; the code is working as it should... here's why:
The page loads and starts running code, it then hits the .get command and then keeps running, obviously making it to the 'alert' you have next. Since the .get function is still working on fetching the data before your page makes it to the 'alert' part... there's nothing to prompt.
You might want to string things together after the .get, using deferred objects. Look into: http://api.jquery.com/deferred.always/
This is a way of tacking on another function inside of the one fetching your data, so they depend on each other.
Simple answer, yes, you can store the data in a global variable and access it elsewhere. However, you must wait until it is ready.
The better way to do it is to instead store the jqXHR globally and simply add a done callback to it when you need to access the data.
var reqDemoTest = $.get(...);
//... some time later...
reqDemoTest.done(function(data){
console.log(data);
});

How does this javascript work?

I'm a javascript noob, and I don't understand why this works:
$().load('/my/url/', {my:data, more:data}, jsFunc());
function jsFunc()
{
$("#myid").val("yep");
}
But not this:
$().load('/my/url/', {my:data, more:data}, function() {jsFunc()});
function jsFunc()
{
$("#myid").val("yep");
}
I tried an $.ajax instead of $.load with the same result. I will be passing the response data to jsFunc() and that is why I need jsFunc() inside the function. I'm sure it is something simple I'm just not very experienced with javascript. Thanks.
Thanks again for all the help. I decided to use $.post because it works best for the situation but now I'm having trouble with the response data. My code looks like this:
$.post('/my/url/', {my:data, more:data}, function(data) {
var strung = JSON.stringify(data)
var parse = jQuery.parseJSON(strung)
console.log(parse.some);}, 'json');
I'm logging to the console to see what is coming back for now and I will add the callback when I see the correct value logged. The process I got from the jQuery api page, but it will only log undefined. When I change parse.some to parse the console log will display the objects and I can select an element and see the correct key:value pair. Any help would be sweet.
Neither works. The first one appears to work, because you call the function jsFunc immediately, it doesn't wait for any response.
If you create an empty jQuery object using $() and use the load method on that, it won't call the server because there is no element where it can put the result.
To specify the callback function you either use the name of a function:
$('#someElement').load('/my/url/', {my:data, more:data}, jsFunc);
or a function expression:
$('#someElement').load('/my/url/', {my:data, more:data}, function() { jsFunc(); });
The first code block will simply call jsFunc() and return the results as the parameter to the load(..) method, which is odd because that parameter is supposed to be a callback function to fire when the load completes, but that works? The callback syntax is more in keeping with the second example (the one I believe you stated doesn't work).
Answer to my second part:
My returned JSON data consisted of many objects, so I had to specify the index and the key to get the value to return.

Lawnchair javascript data "get" does not let me assign into another variable

I am using Lawnchair to save data in js and retrieve it back for my mobile app.
I have this in my js file.
$(document).ready(function() {
//Lawchair set up
db = Lawnchair({name: 'db'},function(e){
console.log('storage open');
});
//store the 'username' key in storage
db.save({key:"username", value: "john"});
var name = ""
db.get("username", function(obj){
name = obj.value;
})
alert(name);
});
The problem is I always get "" in the name. I can never set any variable inside the callback function of "get" from Lawnchair object. Am I missing something?
Any help would be appreciated.
Thanks.
The database operation is asynchronous. Put your alert inside the callback to the ".get()" function.
As a general rule, any time you see a JavaScript API like this:
something(param, param, ... , function(result, result, ...) {
// ...
});
it's a good bet that the function may be an asynchronous mechanism, and that the callback function you supply will only be called later when an event actually transpires. In those cases you have to structure your own code such that activities you need to perform after the operation completes are done in code inside the callback.
(It's not always the case; some functional programming APIs for example take functions as arguments.)

javascript dynamic properties dissapears after succesfully declaring it from json - becomes empty object (not undefined)

var s = store.get('billablexxxx');
if (!s) {
if (false) {
s = {
"something" : 'Value', ....
}
}
}else {
s = new Object;
$.getJSON('Translation/GetIndexLabels', function(data) {
$.each(data, function(key, val) {
s[key] = val;
// temp[key] = val;
})}) ;
}
}
//here i use the variable
But where i use the variable, the dynamic properties dissapaered, it's not undefined but it's an empty object.
However, when it has been set in the $.getJSON() function, all values are added.
What did i do wrong?
Edit:
Fixed the problem by putting it into a function. When i posted the question, i was already close to the answer that i have looked for the last "hour" (weird javascript console results brought confusion).
Thanks for the advice!
The call to $.getJSON() is asynchronous, so the execution will reach the part where you "use the variable" before the asynchronous call completes.
The usual way to deal with this is to have the use of the variable inside a callback function that is referenced in the getJSON() call.
Here's the reference: http://api.jquery.com/jQuery.getJSON/
The getJSON method is asynchronous, it calls your function(data) once it has completed.
At the point which you are using s, the getJSON method has not yet returned so the properties of s have not been initialised.

Categories

Resources