Saving an $http response object as a $scope variab

2020-06-04 07:00发布

问题:

I asked a related question earlier today on stackoverflow but due to both the complexity of the code (not being able to post it) and my own noviceness I wasn't able to really implement a solution from the answers given.

So my question now is, for a code such as:

$http.get(ArbitraryInput).then(function (response) {$scope.data = response});

(you can substitute "then" with "success" above, I use "then" because success is deprecated according to the updated $http api)

How do I actually save the response object in $scope.data? From what I've been doing so far, $scope.data is "undefined" when I later typed in the code:

console.log($scope.data3);

Thanks!

UPDATE ONE

Apparently if I put console.log($scope.data); inside the console will display what I want for $scope.data. But if it is outside, it will remain "undefined" in the console. In other words:

$http.get(ArbitraryInput).then(function (response) {$scope.data = response; console.log($scope.data);});

will return whatever sort of object response was. in the console, but

$http.get(ArbitraryInput).then(function (response) {$scope.data = response;});
console.log($scope.data);

will return "undefined" in the console.

回答1:

You need to leverage the fact that $http.get returns a promise, and chain to that promise in any code that needs to access the resolved data:

app.controller('Ctrl', function($scope, mainInfo){
    var request = $http.get(ArbitraryInput).then(function (response) {
        $scope.data = response; 
        return response; // this will be `data` in the next chained .then() functions
    });

    request.then(function (data) {/* access data or $scope.data in here */});


    $scope.someFunction = function () {
        request.then(function (data) {/* access data or $scope.data in here */);
    };
}) ;


回答2:

Question has been answered, but want to give an alternate solution in case the data is needed immediately. Instead of calling the $http service directly in your controller/directive, you can resolve that data as a dependency in your route, so the data is immediately availble:

angular.module('myApp')
    .config(['$routeProvider', function($routeProvider) {
        $routeProvider.when('/home', {
            templateUrl: '/path/to/template',
            controller: 'myCtrl',
            controllerAs: 'ctrl',
            resolve: {
                myData: ['$http', function($http) {
                    return $http.get('/end/point');
                }
            }
        }
    }]);

Then your controller can look like this:

angular.module('myApp')
    .controller('myCtrl', ['myData', function(myData) {
        var self = this;
        self.data = myData;
    }]);

And in your view:

<pre>{{ctrl.data|json:4}}</pre>

Would display all of your data as JSON without having to call $http in your controller.



回答3:

Try this:

$http.get(ArbitraryInput).then(function (response) {
    $scope.data =     response;
    console.log($scope.data);
});

$http.get is asynchronous. See also this explanation of AJAX



回答4:

Please note that this is a promise (async request) so if you did something like this

$http.get(ArbitraryInput).then(function (response) {$scope.data = response;});
console.log($scope.data)

it might log nothing ,, as you try to log it before the request is finished so you might need to use something like this

$http.get(ArbitraryInput).then(function (response) {
$scope.data = response;
console.log($scope.data);
});

so you are sure that console.log will be executed after the assignment to $scope.data



回答5:

Here is a practical answer, courtesy of user Kirill Slatin. Practical use example at the bottom of the answer.

If, like me, you need to use that response object as a scope variable, here's the trick:

This will return "undefined" in the console, and like me, you probably won't be able to use that response data on your page:

$http.get(ArbitraryInput).then(function (response) {$scope.data = response;});
console.log($scope.data);

However, this should work:

    $http.get(ArbitraryInput)
         .then(function (response) {
            $scope.data = response;
            $scope.$apply()
});

$scope.$apply() is what will persist the response object so you can use that data.

-

Why would you need to do this?

I'd been trying to create an "edit" page for my recipes app. I needed to populate my form with the selected recipe's data. After making my GET request, and passing the response data to the $scope.form, I got nothing... $scope.$apply() and Kirill Slatin helped big time. Cheers mate!

Here's the example from my editRecipeController:

  $http.get('api/recipe/' + currentRecipeId).then(
    function (data) {
      $scope.recipe = data.data;
      $scope.form = $scope.recipe;
      $scope.$apply()
    }
);

Hope that helps!