简体   繁体   中英

The variable scope/nesting of AngularJS variables

I have this angular controller:

app.controller('FeedCtrl', function ($scope, Profile) {
$scope.getID = function() {
    Profile.getUID()
        .then(function (data) {
            if (data !== null) {
                console.log(data.id); // returns correct id
                $scope.data = data;
            } else {
                console.log("Could not retrieve id");
            }
        }, function (error) {
            console.log(error);
        });
    console.log($scope.data); // logs: undefined

    return $scope.data; // logs: undefined
};

var somedata = $scope.getID();
console.log(somedata); //just returns undefined

});

And this Factory that the controller uses for a JSON request.

module.factory('Profile', function($http, $localStorage) {

    return {
        getUID:function(){
            return $http.get("https://graph.facebook.com/v2.2/me", {params: { access_token: $localStorage.accessToken, fields: "id,name,gender,location,website,picture,relationship_status", format: "json" }})
                .then(function(response) {
                if (typeof response.data === 'object') {
                    return response.data;
                } else {
                    // invalid response
                    return $q.reject(response.data);
                }

            }, function(response) {
                // something went wrong
                return $q.reject(response.data);
            });
        }

    };

});

The Question

I am unable to change the value of $scope.data for use outside the $scope.getID function but inside the rest of the FeedCtrl.

If you look on the comments you see what I am getting returned in the console logs.

I've tried to understand this problem by searching here in StackOverflow and Google but it seems that I don't understand the $scope concept of AngularJS.

I am grateful for any push in the right direction.

That's a classic mistake, the code you're calling is asynchronous, look at your console and watch the order of your logs, the log that will return the correct id will be the last one because it will be called only after the promise has been resolved.

Is this enough of a push in the right direction for you?

A very simple example , but it's the same principle.

setTimeout(function(){
  document.write('A2: Timeout is done');
}, 5000);

document.write('A1: Called timeout, this gets logged before A2 even though my line number is higher.');

That is not a scope problem, it's a time problem. You are trying to use the value before it exists.

In the controller you can only use the value after the result has arrived, ie in the callback for the then method. The return statement runs before there is a result, so you can't return it.

Once you have made an asynchronous call, the result has to be handled asynchronously. You can return a Future object to handle the result when it arrives, but you can never make a function that makes an asynchronous call and returns the result itself.

Your code is asynchronous. I wrote a response to this exact same problem in this post.

Returning after ajax call prints false

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM