ecapstone
ecapstone

Reputation: 289

Can't access attribute of Angular Promise

I'm trying to write a JS function using Angular such that I can have it return a value, then set a variable on the scope equal to that value. I return a promise object that according to the chrome console has an attribute with my data in it, but when I try to access that, it says it is undefined.

Code:

   function getData($scope, $http) { //line 71
    output = $http.get('/static/json/tickets').
        success(function(data, status) {
            output.data = data;
            console.log(output.data); //Within the proper scope; displays the data array
            output.status = status;
        }).
        error(function (data, status){
            output.data = data || "Error";
            output.status = status;
        });
        console.log(output); //displays the promise object, with attribute data
        console.log(output.data); // displays 'undefined' (out of scope?)
        return output


    out = getData($scope, $http);
    console.log(out); // Displays the promise object, with attribute data
    console.log(out.data); // displays 'undefined'
    $scope.data = out.data;

Chrome console:

Console.log statements

Is there any way I can put a return statement inside the .success(data, status) function that will make the parent function (getData) return that value? I'm fairly new to JS, and while I know that it's possible to return from a nested function, .success is a method of the promise returned by $http.get, and trying to return output.data gives an undefined object. This code:

function getData($scope, $http) {
dataout = {};
output = $http.get('/static/json/tickets').
    success(function(data, status) {
        dataout = data;
        console.log(output.data); //Within the proper scope; displays the data array
        output.status = status;
    }).
    error(function (data, status){
        output.data = data || "Error";
        output.status = status;
    });
    console.log(output); //displays the promise object, with attribute data
    console.log(output.data); // displays 'undefined' (out of scope?)
    return dataout

returns an undefined object as well, which makes me think that Angular is doing something with async that I'm not handling properly.

Upvotes: 0

Views: 1658

Answers (2)

Rob
Rob

Reputation: 1860

You need to let the promise resolve before you can get the data. Here is an example using a factory and controller:

app.factory('Tickets',function($http,$q) {
    var dataout = $q.defer();

    $http.get('/static/json/tickets/').success(function(data,status) {
            dataout.resolve(data);
    });

    return {
        getData: function() {
            return dataout.promise;
        }
    }
});

app.controller('GetData',function($scope,Tickets) {
    Tickets.getData().then(function(data) {
        $scope.out = data;
    });
});

Upvotes: 2

Konstantin Krass
Konstantin Krass

Reputation: 8646

This is not how you use promises. The output variable get actually logged before the data is there. But the chrome console shows the object in its current data state.

try to log out.data.toString() it will log "undefined".

Try this:

function getData($http) {
 return $http.get('/static/json/tickets').
    success(function(data, status) {
        console.log(data); //Within the proper scope; displays the data array
        return data;
    }).
    error(function (data, status){
        return status;
    });
}

The $http will return a promise in which you attach the success and error callback and by returning a value within these callbacks, angular will wrap a promise around and return it.

And then call it like this:

getData($http).then(function(data){
  console.log(data);
});

Maybe move the method into a service and dont pass the $http as a parameter there.

Upvotes: 2

Related Questions