Reputation: 669
I have a function that makes a GET request for a nested JSON object. The object is returned successfully but you can't access the other objects within the returned object.
the object looks like this :
{
"student": {
"hobbies": ["reading", "dancing", "music"],
"subjects": ["english", "maths", "science"]
}
}
and this is the function :
var superObject = {
getData: function(obj) {
$.get(obj.target, function(callbackObject) {
// It works fine if i log callbackObject
// console.log(callbackObject);
return callbackObject;
}
},
useData: function() {
var data = superObject.getData({'target': 'file.json'});
var hobbies = data.student.hobbies;
console.log(hobbies); // This fails and returns nothing.
}
}
Upvotes: 0
Views: 4300
Reputation: 4841
You could turn your asynchronous AJAX call to be synchronous. See http://api.jquery.com/jQuery.ajax/, mainly the "async" option.
See this discussion:
Ajax jquery synchronous callback success
Upvotes: 0
Reputation: 83358
The problem is that you're returning callbackObject
from your $.get callback, and not from your getData
function. $.get is asynchronous, so its callback will not fire until long after getData()
has finished. That's why you're seeing undefined.
What about something like:
var superObject = {
getReuslts: {},
getData: function(obj) {
$.get(obj.target, function(callbackObject) {
getReuslts = callbackObject;
this.useData();
}
},
useData: function() {
var hobbies = getReuslts.student.hobbies;
console.log(hobbies);
}
}
Of course this would create a temporal dependency between useData and getData. Why not create this object in a function so you can add some encapsulation?
funcition getSuperObject = {
var result = {};
var getReuslts = {};
function useData() {
var hobbies = getReuslts.student.hobbies;
console.log(hobbies);
}
result.getData = function(obj) {
$.get(obj.target, function(callbackObject) {
getReuslts = callbackObject;
useData();
});
};
return result;
}
Or supply your own callback:
var superObject = {
getData: function(obj, callback) {
$.get(obj.target, function(callbackObject) {
if (callback)
callback(calbackObject);
});
}
}
And then
superObject.getData({'target': 'file.json'}, function(result) {
var hobbies = result.student.hobbies;
console.log(hobbies); // This fails and returns nothing.
});
Upvotes: 1
Reputation: 1619
You are returning in the callback handler. So your result is sent to the callback dispatcher which drops your result. What you need to do is attach your processing code to the get callback:
getData: function(obj) { return $.getJSON(obj.target); },
useData: function() {
getData({ target : 'file.json'}).then(function(results) {
var hobbies = results.student.hobbies;
console.log(hobbies);
}
}
Upvotes: 0
Reputation: 15042
Due to asynchronous Ajax behaviour, you need to pass a callback function to execute once the data retrieved via Ajax is available; something like:
getData: function(obj, callback) {
$.get(obj.target, function(callbackObject) {
callback.call(null, callbackObject);
}
}
useData: function() {
superObject.getData({'target': 'file.json'}, function(data) {
var hobbies = data.student.hobbies;
});
}
Upvotes: 1
Reputation: 6266
The scope of your variables is only in your function You can try to set the variable hobbies out of your structure, and set it's value inside of your function
var hobbies; //global scope
var superObject = {
getData: function(obj) {
$.get(obj.target, function(callbackObject) {
// It works fine if i log callbackObject
// console.log(callbackObject);
return callbackObject;
}},
useData: function() {
var data = superObject.getData({'target': 'file.json'});
hobbies= data.student.hobbies;
//set it's value
}
}
Upvotes: 0
Reputation: 437376
$.get
works asynchronously: you call it, then the browser goes off to make the request. Meanwhile, your code continues running. When the browser gets the response from the server, it invokes the callback function you provided passing it the results.
This means that when getData
runs, it will return "almost immediately" and the request started by $.get
will still be in progress in the background. So, getData
cannot return anything meaningful to its caller because it can only schedule a requestl; it cannot know what the result will end up being.
So it follows that you cannot call getData
like this:
var data = superObject.getData({'target': 'file.json'});
What you need to do instead is put the code that depends on the response inside the callback:
$.get(obj.target, function(data) {
var hobbies = data.student.hobbies;
console.log(hobbies); // This will now work
}
Upvotes: 0