admin管理员组

文章数量:1400524

In my controller I have the following...

$scope.products = dataService.getJsonData();
console.log($scope.products);

and in my dataservice I have the following

.service('dataService', function ($http) {

        this.getJsonData = function () {
            return $http.get('path/to/json/products.json').then(function (response) {

                // don't send back everything....
                var productData = response.data;
                console.log(productData);
                return productData;

            });

        };

and in my view I have the following...

<div ng-repeat="product in products">

    Name: {{ product.name }} <br>
    Price: {{ product.price }}
    <hr>
</div>

in my rendered view the repeat is showing only 3 items (products is an array of 15 objects). When looking at the console the repeat in the view or products is made of Object { then=function(), catch=function(), finally=function()} but the log from the dataservice is out putting the desired object array. I don't understand why the output isn't waiting for the returned data, I thought this was asynchronous? How can I make the view wait for the dataservice without using a $timeout. Has anyone else had this problem? Thanks in advance.

UPDATE *

From a bit of googling I'm pretty sure I need to add a resolve to my $routeProvider, the $routeProvider currently looks like so:

.when('/', {
      templateUrl: 'views/main.html',
      controller: 'MainCtrl',
      resolve:{
        // i need to put something here...
      }
  })

In my controller I have the following...

$scope.products = dataService.getJsonData();
console.log($scope.products);

and in my dataservice I have the following

.service('dataService', function ($http) {

        this.getJsonData = function () {
            return $http.get('path/to/json/products.json').then(function (response) {

                // don't send back everything....
                var productData = response.data;
                console.log(productData);
                return productData;

            });

        };

and in my view I have the following...

<div ng-repeat="product in products">

    Name: {{ product.name }} <br>
    Price: {{ product.price }}
    <hr>
</div>

in my rendered view the repeat is showing only 3 items (products is an array of 15 objects). When looking at the console the repeat in the view or products is made of Object { then=function(), catch=function(), finally=function()} but the log from the dataservice is out putting the desired object array. I don't understand why the output isn't waiting for the returned data, I thought this was asynchronous? How can I make the view wait for the dataservice without using a $timeout. Has anyone else had this problem? Thanks in advance.

UPDATE *

From a bit of googling I'm pretty sure I need to add a resolve to my $routeProvider, the $routeProvider currently looks like so:

.when('/', {
      templateUrl: 'views/main.html',
      controller: 'MainCtrl',
      resolve:{
        // i need to put something here...
      }
  })
Share Improve this question edited Mar 14, 2014 at 10:40 Mike Sav asked Mar 14, 2014 at 10:29 Mike SavMike Sav 15.3k31 gold badges102 silver badges150 bronze badges 3
  • Do I need to add a resolve to my $routeProvider perhaps? – Mike Sav Commented Mar 14, 2014 at 10:33
  • I think i usually add a callback to getJSONData to update $scope, instead of returning data – Jorg Commented Mar 14, 2014 at 10:47
  • No, what you need is $apply. I fixed your code in my answer. – bluehallu Commented Mar 14, 2014 at 10:53
Add a ment  | 

4 Answers 4

Reset to default 5

When you call dataService.getJsonData() it doesnt return the data that the $http.get returns, it returns a promise that will be fulfilled with the data in the future. I would remend you to read up on promises. You can read about the angular implementation here.

As I mentioned, the function returns a promise that will be fulfilled, so you need to set the data in the scope when the promise is fulfilled. Change your controller to this:

dataService.getJsonData().then(function (products) {
    $scope.products = products
})

hmm not sure if it will help, because angular is async but try adding this to your controller before using the data.

dataService.getJsonData().success(function (response){
  $scope.products = response
})

With $resource it is a bit easier, like this:

dataService.factory('getJsonData', ['$resource',
  function($resource) {
    return $resource('path/to/json/products.json');
  }
]);

The other parts are the same.

The actual update is happening in a callback, so you need to wrap it in $apply. Because it's happening in a service, you must use $rootscope

.service('dataService', function ($http,$rootScope) {

    this.getJsonData = function () {

        return $http.get('path/to/json/products.json').then(function (response) {
            $rootScope.$apply(function () {
                // don't send back everything....
                var productData = response.data;
                console.log(productData);
                return productData;

            })
        });     
    };

From the angular promises docs

// since this fn executes async in a future turn of the event loop, we need to wrap our code into an $apply call so that the model changes are properly observed.

Edit: As OdeToCode pointed out, this is really not needed. The reason is that what http.get returns is an Angular promise, which is already doing an $apply internally on the .then() callbacks.

本文标签: javascriptAngularJS view doesn39t wait for httpgetStack Overflow