I want to get data in global variable by using the following code:
var data;
d3.json ( "file.json" , function(json) {
data = json;
console.log(data); //defined
});
console.log(data); //undefined
But the problem is that i just have data variable defined in d3.json function but out it is undefined.
how can I solve this issue?
Thanks
Because d3 requests (like d3.json) are asynchronous, it's best practice to wrap all of the code dependent on your external request within the request callback, ensuring that this code has access to the data before executing. From the D3 docs: "When loading data asynchronously, code that depends on the loaded data should generally exist within the callback function."
So one option is to put all of your code within the callback function. If you'd like to separate the code into parts, you can also pass the response from your request to a separate function, something like this:
function myFunc(data) {
console.log(data);
}
d3.json('file.json', function (data) {
var json = data;
myFunc(json);
});
Related
I'm trying to read data from a json file into JavaScript so it can be used by other functions that are called when a user interacts with the page. I've tried, using jQuery and JS:
var products = null;
$.getJSON("products.json", function(data) {
products = data;
console.log(data);
});
console.log(products);
Which produces, as expected:
null
Array [ {…}, {…} ]
I understand this is because of the asynchronous nature of the jQuery code execution. I've read into it a bit, but I'm just struggling to wrap my head around how to re-structure my code (coming from pretty much exclusively Python).
This is how I'm seeing it:
var products = null;
$.getJSON("products.json", function(data) {
products = data;
console.log(data);
});
function do_stuff(){
// Access the attributes of data and do stuff
}
function do_more_stuff(){
// Do some more stuff with the data
}
I would probably have do_stuff() execute when the page body loads, and let's say do_more_stuff executes when the user selects something in a dropdown menu. Both need to access the data in products.json. I know there are many examples out there, but I'm just not getting it. How can I re-structure the code to actually work?
I believe you are looking for something like this:
function get_json(cb) {
$.getJSON("products.json", function(data) {
cb(data);
});
}
function cb(data) {
// do stuff here if you want
console.log(data)
}
get_json(cb)
Create a callback function cb (or call it do_stuff if you'd like). Pass a reference to that function to your async function (get_json). When the async operation is complete, call your callback function with the data you received.
I'm using Jquery's $.getJSON to get remote JSON from a server. The data is returned and stored in a global variable. The reason this variable is global is because I want that variable and it's data inside, to be the value of another variable outside of that function. So far, the variable with the global variable containing the JSON data, as it's value, has been "undefined" due to the rest of the code not waiting on the JSON. So I think a deferred object will help with this issue however I'm new to this idea. Here is my code below. How can I use a deferred object to allow my code to wait for the JSON data then define my variable outside of the function with the global variable containing the JSON data.
function getStuff(num, onContents){
$.getJSON('http://whateverorigin.org/get?url=' + encodeURIComponent('http://catholic.com/api-radio/' + num) + '&callback=?', function(data){
//call the oncontents callback instead of returning
onContents(data.contents);
});
}
//when calling getstuff, pass a function that tells what to do with the contents
getStuff(6387, function(contents){
window.GlobalVar = contents;
});
var NewVar = window.GlobalVar;
alert(NewVar);
It is obvious when reviewing our back-and-forth that there was a lot of confusion in our correspondence. Allow me to sum up:
First, you wanted to define a global variable with the result of your $.getJSON call. Your code was already doing this.
getStuff(6387, function(contents){
// the following statement will assign the value of 'contents' to the global variable 'GlobalVar'
window.GlobalVar = contents;
});
I was focussed on the last two lines of your snippet because they were breaking your code:
var NewVar = window.GlobalVar;
alert(NewVar);
The reason this doesn't work is because window.GlobalVar has not been defined yet. Although the line of code where window.GlobalVar is assigned the value of contents precedes the final two lines in the code, the evaluation of these lines is out of sync because the $.getJSON call is asynchronous (which basically means it has its own timeline). So, window.GlobalVar = contents; has not been executed when var NewVar = window.GlobalVar; is attempted - so the line fails.
Due to the asynchronism, any code that relies on contents has to be executed after the $.getJSON call - which is what you hinted at in your original question when you mentioned "deferreds". This is why I urged you to move your last two lines into your callback. Using a deferred would not have been essentially different from what you were already achieving with your callback - a deferred just allows you to attach multiple callbacks that fire on different events.
We finally established that your issue is specific to Angular JS - that is, how to attach ajax data to your $scope. Whereas using a jQuery deferred would not help you, I think using an Angular deferred will. What you need to do is to replace jQuery's getJSON method with the jsonp method from Angular's http service - this will allow you to attach a 'success' handler which will update your $scope (and your view) when your ajax data arrives:
function getStuff(num) {
$http.jsonp('http://whateverorigin.org/get?url=' + encodeURIComponent('http://catholic.com/api-radio/' + num) + '&callback=JSON_CALLBACK')
.success(function (contents) {
$scope.shows = contents;
});
};
getStuff(6387);
Our ajax response contains an object with a key of 'contents' and a value which is a string of json data, within which is the 'shows' data we want. I'm going to modify the .success handler so that we can get the 'shows' data by deserializing the json string:
.success(function (response) {
var result = angular.fromJson(response.contents);
$scope.shows = result.shows;
});
Next, in our Angular, we want to iterate over each 'show' in 'shows' and we can do this using the ng-repeat directive:
<ul>
<li ng-repeat="show in shows">{{ show.title }}</li>
</ul>
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);
});
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.)
I am confused with the variable scope in Javascript. I am trying to load data file (.json) using Prototype library and parse the response text using json-sans-eval. The problem is it seems to me that the content from data file is lost if I tried to access "dataObj" outside of the Ajax.Request scope.
The variable in Javascript has reference count. I don't understand how can the global variable 'dataObj' will lose its data. Any hint or help?
Thank you!
var dataObj;
function OnLoadHandle() {
new Ajax.Request('data.json',
{
method:'get',
onSuccess: function(transport)
{
var response = transport.responseText || "no response text";
dataObj = jsonParse(response);
console.log(dataObj["[0,0]"]); // OK
},
onFailure: function(){ alert('Something went wrong...') }
});
console.log(dataObj["[0,0]"]); // ERROR
}
The second invocation of console.log(...) at the end of OnLoadHandle runs immediately, whereas the one inside onSuccess runs only after the request completes. The second console.log serves no purpose.
More broadly, this means that there is no point in making dataObj a global variable. It is only useful after it is assigned in onSuccess and should therefore be scoped as a local variable within onSuccess. If you need it elsewhere, onSuccess should pass it as a parameter to some other function.