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
});
Related
Just wanting to populate myObj with data from within the get request. According to my console.log(myObj) everythings seems to be their but can't access. I'm sure their is a simple answer to this. Thanks.
function getInfo() {
var myObj = {};
$.get("http://ipinfo.io", function(response) {
myObj.city = response.city;
myObj.region = response.region;
}, "jsonp");
console.log(myObj.city); //undefined
return myObj;
}
var myStuff = getInfo(); //Object {} just as I expected obviously.
console.log(myStuff) // Object shows all my key value pairs but -->
console.log(myStuff.city); // undefined why?
It is more suitable to use promises. You can try something like this:
function getInfo() {
var dfd = $.Deferred();
$.get("http://ipinfo.io", function(response) {
myObj.city = response.city;
myObj.region = response.region;
dfd.resolve(myObj);
}, "jsonp");
// Return the Promise so caller can't change the Deferred
return dfd.promise();
}
getInfo().done(function(myStuff) {
console.log(myStuff);
console.log(myStuff.city);
});
With promises the code is one idea elegant.
$.get is an asynchronous operation which means that it returns immediately (without running the code in your callback function first). The callback will only be executed at some point in the future when the GET request is finished. In the meantime the code following the $.get call will be executed.
What you're seeing is a result of a specific execution order in which the GET request happened not to finish before the following code was executed. In other words you have a race condition.
In theory , if the GET request finished almost instantly, it would be possible for the callback to execute before your log statements and therefore not print undefined. This is highly unlikely, however, as the time it takes to execute log instructions are much(!) less than what it takes to execute the GET request.
To fix the issue you need to ensure that you're log statements are always run only after the GET request is finished. The idiomatic way to do this in JS is with callbacks - e.g. pass a function which contains the code to execute and call it from inside the response handler:
function getInfo(callback) {
var myObj = {};
$.get("http://ipinfo.io", function(response) {
myObj.city = response.city;
myObj.region = response.region;
callback(myObj);
}, "jsonp");
console.log(myObj.city); //undefined
}
getInfo(function(myStuff) {
console.log(myStuff)
console.log(myStuff.city);
});
It return undefine because the request didn't response yet then the function returned the value. Your request was asynchronous meaning your function wont wait for your get request. it would return what ever myObj is.
You can try something like
function getInfo(callback){
$.get(..., function(res){
var myObj = …;
callback(myObj);
}
}
when ever your request is finished, it would call the callback function and pass in the myObj. so you need to pass in a anonymous function that expect 1 argument to pass in the myObj from the response
getInfo(function(data){
//data should be myObj
});
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I have the following code
function test(){
var api_url = "/Test/";
api.CFClient.load(api_url,function(success){
success.images; // Object with images
},function(error){
});
// More code to use the images returned.
I am basically unable to get the images from the success function. If i execute my code within the success function i am able to access the returned object. How do i store the returned object in a variable so i can use that object in my parent function and not the success function ?
I presume api.CFClient.load is asynchronous, and in that case you can't access success.images immediately in the test() function after invoking the load function. It will be available at some unknown time in the future, when the ajax request has completed. You'll have to invoke a different function from within your success callback and do whatever you need to do with success.images there, or else do what you need to do directly in the success callback function.
You need to account for the success function being asynchronous. You won't be able to use the returned images until the api call is complete. When it is, you can call another function and pass the images.
function test(){
var api_url = "/Test/";
api.CFClient.load(api_url,function(success){
useImages(success.images);
}, function(error){
});
function useImages(images) {
// do something with images here...
}
SO is full of errors like this(asynchronous workflow), just google for...
function test(){
var api_url = "/Test/";
function useImages(err, images) {
if (err) return console.error(err);
console.log(images);
}
api.CFClient.load(api_url,function(success){
useImages(null, success.images);
},function(error){
useImages(error);
});
}
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.
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.
I have a problem returning a variable in my function, the below script works fine:
function sessionStatus(){
$(document).ready(function(){
$.getJSON(scriptRoot+"sessionStatus.php",function(status){
alert(status);
});
});
}
sessionStatus();
Bet when I try the following I get a message box with the message "undefined":
function sessionStatus(){
$(document).ready(function(){
$.getJSON(scriptRoot+"sessionStatus.php",function(status){
return status;
});
});
}
alert(sessionStatus());
This is really bugging me, I just can't seem to see what I've done wrong.
There are two things you should know:
1: the JSON thing is asynchronous, so the function call to sessionStatus could already be done when the JSON is still being fetched. The following would work:
function sessionStatus(callback){
$(document).ready(function(){
$.getJSON(scriptRoot + "sessionStatus.php", function(status){
callback(status);
});
});
}
sessionStatus(function(s){alert(s);});
or rather:
function sessionStatus(callback){
$(document).ready(function(){
$.getJSON(scriptRoot + "sessionStatus.php", callback);
});
}
sessionStatus(function(s){alert(s);});
2: even when it would be synchronous, you are only giving a return value from the inner function, so the sessionStatus would return nothing. Check out this code (not related to your JSON thing):
function do() {
var x = 0;
(function(){
x = 2;
})();
return x;
}
or:
function do() {
var x = (function(){
return 2;
})();
return x;
}
Both return 2. Hopefully this explains a bit.
Your function sessionStatus() doesn't return anything, hence the alert says undefined.
All the function does is set thing up for the AJAX call to happen once the page loads - nothing actually happens within sessionStatus() that could be returned.
The code in function(status) { ...} doesn't get run until the AJAX call to the server returns a value, and that AJAX call doesn't get sent until the page loads.
You ought to read up on what $.getJSON() and $(document).ready() actually do, because you're going to continue to get confusing behaviour until you understand them properly.
Your sessionStatus() function never returns anything. It sets a function to run later, and that function returns something, but that's not anything to do with sessionStatus()
You're returning a value when the document ready event is done. Where is your value supposed to go? The jQuery object doesn't know what to do with it.
The function sessionStatus just sets up the event listener for $(document).ready() and then returns without returning a value. That's the undefined you see.
Later when $(document).ready() fires it calls the ajax which if it succeeds returns the status, but nothing is receiving that status.
function sessionStatusCallback(status)
{
alert(status);
}
function sessionStatus(){
$(document).ready(function(){
$.getJSON(scriptRoot+"sessionStatus.php",function(status){
sessionStatusCallback(status);
});
});
}
sessionStatus();
Your function is being called asynchronously -- actually after two asynchronous calls, made via .ready() and .getJSON(). In such a case there is no available return value, instead you have to use a callback, as in the above, to process the response.
Though I should note that the function passed to getJSON in the above already is a callback. You could change that function definition to just be "sessionStatusCallback" and it would call the above callback once the JSON was ready, and you could continue to process there. Or...continue your processing in the current callback (it's a matter of style whether to use a function reference or declare the anonymous function right there in the .getJSON() call)
Functions should never be included in a jQuery(document).ready function. Separate them, so you don´t have side effects you don´t want to have. How do you want to call the session status? And witch function should get the return value?