简体   繁体   中英

AngularJS factory

Im kinda new into angularjs and I'm trying to create a small movie database. Its the first time im using a factory and I wanted to make sure this is the right way to do it and how to use this factory in another function as display below?

I want this factory to run only once, so I could use it in any controller I like. However I'm lost why I can't use $scope.allMovies in the example below. Thanks in advance!

var app = angular.module('myApp', []);

app.factory('moviesService', ['$http', function($http) {

  var allMovies = [];

  var getMovies = function() {
      $http.get('js/data.json').success(function(data) {
          angular.forEach(data, function(movies) {
          allMovies.push(movies);         
      });
  })
}

getMovies();

var getAllMovies = function(){
      return allMovies;
}

return {
    getAllMovies: getAllMovies
};

}]);

app.controller('listController', ['$scope', 'moviesService', function($scope,moviesService) {

$scope.genres = ['All', 'Crime', 'Drama', 'Action', 'Comedy'];

$scope.allMovies = moviesService.getAllMovies();

$scope.moviesByGenre = [];

$scope.selectedGenre = 'All';

$scope.getMoviesByGenre = function() {
    // code to get movies by genre goes here
    // cant access $scope.allMovies from here, returns as an empty array
};
}]);

My index.html looks like:

<div ng-controller="listController">
    <div ng-repeat="movies in allMovies">{{movies.title}}</div>
</div>

This works, I have a list of the movies.title i get from the data.json.

However, when I try to console.log $scope.allMovies from inside of the function getMoviesByGenre I get an emtpy array.

getMovies has asynchronous function $http.get, so you need use callback like this,

var app = angular.module('myApp', []);

app.factory('moviesService', ['$http', function($http) {
    var getMovies = function (callback) {

        $http.get('js/data.json').success(function(data) {
            var allMovies = [];

            angular.forEach(data, function(movies) {
                allMovies.push(movies);
            });

            callback(allMovies);
        })
    }

    return {
        getAllMovies: getMovies
    };
}]);

app.controller('listController', ['$scope', 'moviesService', function($scope, moviesService) {
    $scope.genres        = ['All', 'Crime', 'Drama', 'Action', 'Comedy'];
    $scope.moviesByGenre = [];
    $scope.selectedGenre = 'All';

    $scope.getMoviesByGenre = function () {
        moviesService.getAllMovies(function (allMovies) {
            console.log(allMovies);    
        });
    };
}])

or use promises

I think you are miss using getMovies() inside the factory. getMovies() callback should return the ajax request result not pushing to other variable because of the asynchronous ajax call.

var getMovies = function() {
  $http.get('js/data.json').success(function(data) {
       return data; 
  });
}

return {
    getAllMovies: getMovies
};

this is because the http request inside your service is executed asynchronously. To overcome this problem you can use a $watchCollection function which will be executed after you modify the all movies array inside moviesService:

app.controller('listController', ['$scope', 'moviesService', function($scope, moviesService) {
   $scope.genres = ['All', 'Crime', 'Drama', 'Action', 'Comedy'];

   $scope.allMovies = moviesService.getAllMovies();

   $scope.moviesByGenre = [];

   $scope.selectedGenre = 'All';

   $scope.getMoviesByGenre = function() {
       // code to get movies by genre goes here
       // cant access $scope.allMovies from here, returns as an empty array
   };
  $scope.$watchCollection('movies', function (newValue) {
      getMoviesByGenre();
  });
});

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