Robert Wilson
Robert Wilson

Reputation: 669

Pass or return JSON Object from jQuery GET

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

Answers (6)

Nick Bork
Nick Bork

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

Adam Rackis
Adam Rackis

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

Bashwork
Bashwork

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

jabclab
jabclab

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

vorillaz
vorillaz

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

Jon
Jon

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

Related Questions