Scope in JavaScript / jQuery [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I've clearly been writing too much CoffeeScript, as I am now realizing I do not have even a basic understanding of scope in pure JS.
After playing for a while, I cannot figure out the problem with the following--
$(document).ready(function() {
var myUrl = "http://notimportant.com/"
var photos = getPhotos(myUrl);
console.log(photos); //undefined
});
function getPhotos(url) {
var a;
$.get(url, function(data) {
a = data["photoset"]["photo"];
console.log(a); //my object
});
return a;
}
If I put a console.log(a) statement on the line right below 'var a = data["photoset"]["photo"];' it shows that it properly makes the GET request I'm looking for. But I'm finding it impossible to pass that object back to my main block of code, where I want to manipulate it.
Thanks in advance.

The reason photos is undefined is not because of scopes. Its because $.get is executed asynchronously. $.get() returns jqXHR object instead of an HTTP response.
onSuccess callback should be passed to getPhotos() in order to make it work correctly. Alternatively when().then() construct could be used.
$(document).ready(function() {
var myUrl = "http://example.com/";
getPhotos(myUrl, renderCatPhotos);
});
function getPhotos(url, onSuccess) {
$.get(url, onSuccess);
}
function renderCatPhotos(data) {
var a = data.photoset.photo;
console.log(a); // a is always available
}
note: you might not even need getPhotos function. You can simply $.get(url, onSuccess); in $(document).ready() instead.

Its not a matter of scope, its a matter of that you are returning an undefined variable before the $.get defines it. Consider making photos a global, then setting it in the $.get success function instead of setting it to 'a'. Inside the success function, you can then issue calls to other functions that would control displaying/processing the photos.

Related

Read variable inside function in Javascript? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
Right now I have three files, two javascript files and one html file that will call upon these two javascript files. Inside my first javascript file, let's call it part1.js, I have this content:
var dataval;
$.get('example.cgi', function(data){
dataval = data;
});
Inside part2.js, I am trying to call on this dataval value. But it is not working, as I am assuming that dataval is inside the get function and is therefore a local value. Is there anyway I can grab that value? My html file is calling on both of these javascripts. Is there anyway I can access that variable?
Thanks!!
There is a problem here with asynchronous calls. You should either use a callback function or make use of the jquery promise capability.
In your part1.js, you should instead define a function:
function callCgi(callback) {
$.get('example.cgi', callback); //Callback will receive the data.
}
and then use it in part2.js:
callCgi(function(data) {
//do something with data.
});
Or with promises:
function callCgi() {
return $.get('example.cgi');
}
and then use it in part2.js:
callCgi().then(function(data) {
//do something with data.
});

global var in javascript issue [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I'm newbie and have to following question:
i declared a global variable and alter the value within a function. But outside the value is still the old.
var allowDrag = 'false';
$.get('/cakeorga2/ajax/is_admin/', function (data) {
allowDrag = data;
console.log ('allowDrag in function : '+allowDrag);
});
console.log ('outside of the function : '+ allowDrag);
the console log was:
outside of the function : false
allowDrag in function : true
Any suggestions?
$.get is a shorthand method of $.ajax:
Perform an asynchronous HTTP (Ajax) request.
An ajax call is usually async so the main console.log will be fired before the $.get execution is completed (as you can see in the console order) and in that moment the allowDrag value is still false.
You were trapped. Global variables behave exactly as you expected. The reason it does not have the new value in your second console.log is a different one: By the time you execute the console.log, the ajax call issued with $.get has not been answered yet. If you need to use it like that you must make the call synchronous by using the async: false option.
Use deferred.then() to call the second console.log() only after the value has been updated (ajax GET has been successful)
$.get('/cakeorga2/ajax/is_admin/', function (data) {
allowDrag = data;
console.log ('allowDrag in function : '+allowDrag);
}).then( function(){
console.log ('outside of the function : '+ allowDrag);
}
);
http://api.jquery.com/deferred.then/
This happens because your ajax call is asynchronous. Asynchronous (in your use case) means your outside of the function console.log will execute before your ajax call returns.
Do it synchronous with $.ajax()
var allowDrag = 'false';
allowDrag = $.ajax(
{
url:'/cakeorga2/ajax/is_admin/',
async:false
}).responseText;
console.log ('outside of the function : '+ allowDrag);
Well that might very well be because the console.log outside the function gets called before the one inside the function since you have to call the function yourself and the code around it gets "played" automatically. But since I'm not familiar with Ajax/jQuery I could be wrong.

javascript variable scope issue undefined [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 9 years ago.
function getData() {
var photo,
comment,
url;
$.getJSON('http://url.info/verify/settings.php', function (data) {
photo = data.photoMSG;
comment = data.commentMSG;
url = data.photoURL
});
console.log(photo); //undefined
console.log(comment); //undefined
console.log(url); //undefined
}
I'm getting undefined in console log for all of them... How to get these 3 vars visible outside of getJOSN block? I know this have been asked x100 times, I tried windiw.varName but still the same thing..
It's not a scope issue, it's an asynchronous issue. Everything inside the getJSON handler is asynchronous -- so the console.log calls will usually happen after the variables get assigned. Use an async callback instead:
$.getJSON('http://url.info/verify/settings.php', function (data) {
photo = data.photoMSG;
comment = data.commentMSG;
url = data.photoURL;
callback(photo, comment, url);
});
function(photo, comment, url) {
console.log(photo); //undefined
console.log(comment); //undefined
console.log(url); //undefined
}
Because $.getJSON is doing an ajax call, but the code after that is called before the callback within the getJSON is called. So the vars are still undefined. A typical "problem" with asynchronous behaviors.

Returning array from d3.json() [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
As a JQUERY/d3-noob, it seems I cannot figure out how to make this work:
supdog = d3.json(dataPath, function(jsondata){
return jsondata;
})
console.log(supdog);
Thanks in advance.
Besides the fact that your problem description is very terse, the problem seems to be your assumptions about what is returning what.
The function d3.json() is an asynchronous function that directly returns (with an undefined value I assume). Only when the data is received from the backend, the callback function you passed to it will be called. Obviously the context is different here and the return value of your callback will not automatically become the return value of d3.json (as this one has returned "long" before already).
What you want to do is probably something like:
var jsondata;
d3.json(dataPath, function(dataFromServer) {
jsondata = dataFromServer;
}
console.log(jsondata);
Update 1:
Obviously, the above example is still not fully correct. The call to console.log() is made directly after the d3.json() returned. Thus, the server might not have sent the reply fully yet. Therefore, you can only access data when the callback is returned. Fixed example:
var jsondata;
function doSomethingWithData() {
console.log(jsondata);
}
d3.json(dataPath, function(dataFromServer) {
jsondata = dataFromServer;
doSomethingWithData();
})
For a (somewhat stupid, but) working example see: http://jsfiddle.net/GhpBt/10/
Update 2:
The above example demonstrates in which order the code is executed but does not really deserve a price for most beautiful code. I myself would not use this "global" variable and simplify the above example to:
function doSomethingWithData(jsondata) {
console.log(jsondata);
}
d3.json(dataPath, doSomethingWithData);
Note how doSomethingWithData is directly passed to d3.json in stead of calling it separately in an anonymous inner function.
Note: This is not a particular problem of d3.js. Basically, all javascript functions that are asynchronous are likely to behave in a similar way. If they return something, it will not be the return value of the passed callback.
Solutions do not work anymore, if you start with the current d3 version. New solution -> Code within d3.json() callback is not executed
Then it must be...
d3.json("filename.json")
.then(function(data){
console.log(data);
});
I'm aware that this is a very old post, but I've faced a similar problem recently, and found the following solution, which might worth sharing:
In my case the JSON file's syntax was broken. By default, no errors pop up in the browser in this case, unless you enhance the function suggested by #BertjanBroeksema with errorhandling. Something like this:
function doSomethingWithData(error, jsondata) {
console.log("error:", error)
console.log(jsondata);
}
This way you'll see if there was something wrong with the processing of the JSON file.

$.getJSON to make its result global [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I'm using the jQuery function $.getJSON to get some data from the server side and here is the code:
function (){
$.getJSON("someURI",function(result){
//this alert works fine
alert(result.msg)
});
// this prints the data as undefined
alert(result.msg);
}
how to change the scope of "result" returned from $.getJSON in order to make it global.. to make the second alert prints its value not to be undefined ??
You can't. AJAX is asynchronous meaning that you can access the result variable only inside the success callback. You could make it global, but remember that the line immediately following the $.getJSON call will be called much before the success callback executes rendering it useless.
So no global variables, consume the results of an AJAX call inside the callback:
function () {
$.getJSON('someURI', function(result){
// only here you can hope to consume the results of an AJAX call
alert(result.msg)
});
}
That's how AJAX works. The A in AJAX stands for asynchronous.
This is an asynchronous call.. So you must wait till the server responds...
In your case, the outer alert will be undefined as the server hasn't responded yet...
Also, the scope of result is limited to callback function, it's inaccessible...
You can do it like this though:
var myJSON;
var serverResponded = 0;
function () {
$.getJSON("someURI", function (result) {
//this alert works fine
myJSON = result.msg;
serverResponded = 1;
});
setTimeout(function () {
if (serverResponded) {
alert(myJSON);
}
}, 500);
}
The $.getJSON call is a shortcut to an Ajax call, and “Ajax” stands for “Asynchronous JavaScript and XML”.
Let's suppose you add var globalResult and that you perform a globalResult = result; in your success function. So, when you do a call to globalResult outside the callback, globalResult won't be assigned yet. So, if you really have to process it outside, you can check if it's assigned with a function called setInterval, but this is going too far.
save it into another variable something like this
function (){
var something;
$.getJSON("someURI",function(result){
//this alert works fine
alert(result.msg)
something = result
});
if you want it to be scoped outside your function wrapper, do something like this
var something;
function (){
$.getJSON("someURI",function(result){
//this alert works fine
alert(result.msg)
something = result
});

Categories

Resources