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 in a large local .json file to be manipulated in the code I'm testing. The below snippet loads it in, and returns it to my console.
var dataset;
$.getJSON("data.json", function(json) {
dataset = json.rows;
console.log(dataset);
});
However, when I put console.log() outside of the function, as below, I get "undefined" returned in the console, and receive errors elsewhere when trying to use the "dataset" variable.
var dataset;
$.getJSON("data.json", function(json) {
dataset = json.rows;
});
console.log(dataset);
New to JavaScript, but I thought you could alter an the external variable if it's declared outside of the function? Is there something with jquery or this particular function that I'm missing? The goal is to load the json's rows into a JavaScript object for manipulation, not limited to any scope.
Thanks!
You are correct about being able to alter an the external variable if it's declared outside of the function.
But the jQuery function getJSON is an asynchronous function by default which means when console.log(dataset); is called the dataset variable is still undefined.
If you were to switch console.log(dataset); to setInterval(console.log(dataset), 5000);.
It would probably work but it now relies on the assumption of it always taking less or equal to than 5 seconds.
You can resolve the issue by setting your global ajax configs to disable asynchronous.
This code should work as you intend:
// Switch to synchronous functions.
$.ajaxSetup({ async: false });
var dataset;
$.getJSON("data.json", function(json) {
dataset = json.rows;
});
console.log(dataset);
I am loading a geoJSON file using ajax so that I can push the coordinates of the geoJSON MultiPoint feature that is in the file into a (global) array for use in another function. I am having a problem with my callback function, I think. In the code below, I intend to load the data file and push the data pertaining to certain whales into the multipointCoords array. This works fine, but multipointCoords array is not available globally while whales is available. This is confusing me.
This code is also using OpenLayers.
var whales = {};
var multipointCoords = [];
$.getJSON('data/BW2205005.geojson', function(data) {
data.features.forEach(function(feature) {
if (!whales.hasOwnProperty(feature.properties.name)) {
whales[feature.properties.name] = {
"type": "FeatureCollection",
"features": []
};
}
whales[feature.properties.name].features.push(feature);
whales["Free Willy"].features.forEach(function(feature) {
multipointCoords.push(feature.geometry.coordinates);
});
console.log(multipointCoords[0][0]); // gives the right coordinate
});
});
console.log(whales); // is defined
console.log(multipointCoords[0][0]); // is undefined
I have studied the following and still can't fix it:
How to load Open layers 3 geojson vector layer with bbox?
How do I return the response from an asynchronous call?
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
http://api.jquery.com/jQuery.getJSON/
Thanks for any help.
While making ajax calls, we are uncertain about when the success callback will fire, hence we user callbacks in such situations. And pass function as an argument to the called function. In callback function we can pass the data retrieved in ajax response. I could see you are using global-variable in your snippet but you are using them synchronously, in that case value of global-variable is not updated(Values used before ajax success callback)
Try this:
function geoJSON(callback) {
var whales = {};
var multipointCoords = [];
$.getJSON('data/BW2205005.geojson', function(data) {
data.features.forEach(function(feature) {
if (!whales.hasOwnProperty(feature.properties.name)) {
whales[feature.properties.name] = {
"type": "FeatureCollection",
"features": []
};
}
whales[feature.properties.name].features.push(feature);
whales["Free Willy"].features.forEach(function(feature) {
multipointCoords.push(feature.geometry.coordinates);
});
if (typeof callback === 'function') {
callback(whales, multipointCoords);
}
});
});
}
geoJSON(function(whales, multipointCoords) {
console.log(whales);
console.log(multipointCoords);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
You array is defined as an empty array, but its first member - not yet.
You are trying to access your array members before your callback fetches the data and process it. To fix it you may use promises.
var whales = {};
var multipointCoords = [];
$.getJSON('data/BW2205005.geojson')
.then( function(data) {
data.features.forEach(function(feature) {
if (!whales.hasOwnProperty(feature.properties.name)) {
whales[feature.properties.name] = {
"type": "FeatureCollection",
"features": []
};
}
whales[feature.properties.name].features.push(feature);
whales["Free Willy"].features.forEach(function(feature) {
multipointCoords.push(feature.geometry.coordinates);
console.log(multipointCoords[0][0]); // gives the right coordinate
});
});
})
.then( function() {
console.log(whales); // is defined
console.log(multipointCoords[0][0]); // is undefined
});
multipointCoords[0][0]) will be always undefined because you're trying to access a value which is not even initialized by the time your console.log() executes.
Even though it looks like the statements in your code are executed in top-bottom fashion, $.getJSON() is an Asynchronous operation, so JS interpreter will fire your AJAX call (via $.getJSON) and continue to execute the remaining statements in your script. The callback that you're passing to $.getJSON() is invoked only when your AJAX call is success and some response is available.
I've attached a screenshot trying to depict the way in which your statements are executed. As shown below, by the time step 5 is executed, multipointCoords is not populated with your expected data as $.getJSON's callback is not invoked yet. Once the AJAX call is done, callback is invoked (Step 6) and multipointCoords is populated with your expected values. Hence the console.log() inside your callback prints some valid value.
If you intend to use multipointCoords in some other function, you can either invoke that other function in the success callback of $.getJSON or use Promises.
$.getJSON('data/BW2205005.geojson', function(data) {
data.features.forEach(function(feature) {
/* do your logic here
populate multipointCoords*/
multipointCoords.push(feature.geometry.coordinates);
});
}).done(function(){ // done is called only for success scenarios
anotherFunction(multipointCoords);
}).fail(function{
// AJAX call failed, multipointCoords is not populated, handle it
});
Hope this helps :)
I'm experimenting with JQuery and trying to create a function to get dynamic data from a JSON returned API and store it in a global variable (I don't know if this is the right/best way to do this).
What I have so far is
function getdata(url){
var data = $.ajax({
type: 'GET',
url: url
});
return data;
};
So far everything works fine, but this returns an object with a "responseJSON" key and I can't seem to find a way to navigate to this key and then do a $.each loop through the arrays in it.
So the questions are:
Is this the right / way ( if not please explain your answer)
How do you navigate through a multidimensional object containing arrays in the "responseJSON" key.
Another approach is to pass a callback to your function so you can set the response handler within the function and less code when you call your getData method
function getdata(url, callback){
var data = $.ajax({
type: 'GET',
url: url
}).done(callback).error(function(){
alert('Oppps...something went wrong')
});
return data;
};
getData('urlstring', function(data){
/* doSomething with data */
})
AJAX is asynchronous. That means it runs in the background while the rest of your script runs. At a point in the future when the AJAX call completes, then you can access it.
In jQuery, $.ajax returns a promise. So what you can do is the following:
getdata('/path/to/your.json').done(function(data){
// Use your JSON data here
console.log(data);
});
What happens is that once the AJAX call is done, your .done() function will run and you will have access to the data returned.
Don't try to access the properties of the $.ajax object (the responseJSON won't be populated until the call is finished). Use callbacks to get at the returned data.
If you want the json data to be in global scope, just define a global variable (that is, outside the function), and then in the function fill it with the returned data. Something like so:
var api_response;
function get_data(url) {
$.post(url, function(j) { api_response = j; }, "json");
// or
$.getJSON(url, function(j) { api_response = j; });
}
You don't even need to create a function for this and can use jquery's own $.getJSON (the or case).
I apologise if this is a repeated question. I have done my research but I am still unable to come up with an answer:
I am writing a small JSONP API. The desired outcome:
The programmer creates an instance of the JSON class.
var json = new jsonpRequest (
"http://url.to.web_service",
searchParam //passed in as an associative array
);
The programmer then declares var myJSON = jsonpRequest.getJsonP()
This will return the JSONP into the myJSON variable to be processed.
The API successfully takes in the parameters when the instance of the class is constructed, generates a link to the services w/ the desired parameters and injects it into the DOM via script tags using this function:
jsonpRequest.prototype.fetchJsonp = function(){
var request = that.getRequest();
//creates a script element
var jsonpCall = document.createElement('script');
//gets jsonp request
jsonpCall.src = request;
//adds script to DOM, which goes on to request the JSONP from the service.
document.head.appendChild(jsonpCall);
};
EDIT: For the sake of clarity: this definitely does return the data set that is requested.
The function I am using as my callback is:
jsonpRequest.prototype.processCallback = function(data){
alert(data);
that.setListOfResults(data);
};
It is called in the link as: &callback=jsonpRequest.prototype.processCallback
The processCallback function takes in the data from the request and stores it in a variable within the class using the setListOfResults function.
After the data has been stored I would like to return the data from the request to the myJSON variable. This is the getJsonp function that the programmer invokes in step 2 of the process:
jsonpRequest.prototype.getJsonp = function(){
that.buildRequest();
that.fetchJsonp();
return that.listOfResults;
};
The issue:
Here is what I am calling after I define my JSON API class:
var myJSON = json.getJsonp();
console.log(myJSON);
Because it is asynchronous, it is moving on to the console log before the callback function is invoked, resulting in MYJSON to be undefined. I am not sure how I can daisy chain my code together in such a way where it runs the callback before moving on.
I tried to emulate the solution from How can I get this JSONP call to return a value?. I may be missing a step or I am perhaps ignorant of something! Any help to clarify this would be greatly appreciated. Thank you in advance :).
P.S. I would like to avoid using JQuery etc... It would be beneficial to keep this strictly as raw JavaScript.
I am not sure how I can daisy chain my code together in such a way where it runs the callback before moving on.
You can’t do that. You must rely on callbacks. Add a callback parameter to your jsonpRequest constructor, and invoke that callback after you do setListOfResults(data). You may also wish to allow for setting the this context in which the callback will be executed.
jsonpRequest.prototype.processCallback = function(data){
alert(data);
that.setListOfResults(data);
that.callback.apply(that.context, [data]);
};
I am having a problem, or perhaps a lack of understanding, with the jQuery execution order of $.get() function. I want to retrieve some information from a database server to use in the $.ready() function. As you all know, when the get returns, it passes the data to a return handler that does something with the data. In my case I want to assign some values to variables declared inside the ready handler function. But the problem is, the return handler of $.get() does not execute until after ready has exited. I was wondering if (a) am I doing this right/is there a better way or if (b) there was a way around this (that is, force the get return handler to execute immediately or some other fix I'm not aware of). I have a feeling this is some closure thing that I'm not getting about JavaScript.
As per request, I'll post an example of what I mean:
$(function() {
var userID;
$.get(uri, function(returnData) {
var parsedData = JSON.parse(returnData);
userID = parsedData.userID;
});
});
So as you can see, I'm declaring a variable in ready. Then using a get call to the database to retrieve the data needed. Then I parse the JSON that is returned and assign the userID to the variable declared before. I've tested it with a couple alerts. An alert after the get shows userID as undefined but then an alert in get's return handler shows it to be assigned.
$.get() is asynchronous. You have to use a callback to fill your variable and do the computation after the request is complete. Something like:
$(document).ready(function(){
$.get( "yourUrl", function( data, textStatus, jqXHR ) {
var myData = data; // data contains the response content
// perform your processing here...
registerHandlers( myData ); // you can only pass "data" off course...
});
});
// your function to register the handlers as you said you need to.
function registerHandlers( data ) {
// registering handlers...
}
$.get is an ajax request. A in AJAX stand for asynchronous, so script won't wait for this request to finish, but instead will proceed further with your code.
You can either use complete callback or you can use $.ajax and set async to false to perform synchronous request.
The $.get() function executes an async httprequest, so the callback function will be executed whenever this request returns something. You should handle this callback outside of $.ready()
Maybe if you explain exactly what do you want to do, it would be easier to help!
Are you looking for something like:
$(document).ready(function(){
var variable1, variable 2;
$.get('mydata.url', function(data){
variable1 = data.mydata1;
variable2 = data.mydata2;
});
});
If you declare the variables first, then you can set their values within the get call. You can add a function call at the end of the get handler to call a separate function using these values? Without some kind of example, its hard to go into any more detail.
Without seeing the full code, my guess is that you should declare your variable outside $.ready; initialize it in ready for the initial page load; then update it from the get callback handler.
for example
var x = ""; // declaration
$(document).ready(function() { x = "initial value"; });
$.get(...).success(function() { x = "updated from ajax"; });