Angular 工厂和服务工作但未达到预期

Angular Factory and Service work but not as expected

我的应用正在查找 google 地点详情并显示部分信息。我在 json 文件中有一个按场所类型细分的地点 ID 列表。工厂访问 id 并将其提供给控制器。我还有一个循环遍历所有 id 的服务,查找详细信息并将它们添加到控制器可用的对象中。

我可以让它工作,因为我可以访问 json 数据、查找详细信息和 return 对象。但是,无论我怎么做,如果我尝试 return 多个对象,每种对象对应一个对象,我就会将所有业务放在一起,否则会出现错误(稍后会详细介绍)。

我已经用多种方法构建了它,但我将展示我尝试过的两种方法的代码。我是 Angular 的新手,所以我可能完全错了,甚至没有正确使用服务和工厂,所以请放轻松。

locations.json

{
  "restaurants": {
    "Michaels": "ChIJwaTJAL4n5IgRgyJupbpQhjM",
    "Collage": "ChIJw5HgNzAm5IgRqbkEqKXIpC4",
    "Scarlet": "ChIJT9ImkZUn5IgREb1hYwKA1Nc",
    "Maya": "ChIJofgqBJYn5IgRVa-HQvp6KDk",
    "Ice": "ChIJnXpQpewn5IgR7k9yxWXUu1M",
    "Sangrias": "ChIJITcc_ZUn5IgR90iEna6FRGM",
    "Columbia": "ChIJ8xR18JUn5IgRfwJJByM-quU",
    "Harrys": "ChIJ8aLBaJYn5IgR60p2CS_RHIw"
  },
  "bars":
    {
      "Scarlet": "ChIJT9ImkZUn5IgREb1hYwKA1Nc",
      "Lion": "ChIJqVCL_b0n5IgRpVR5CFZWi4o",
      "Tradewinds": "ChIJpwF4ZJYn5IgRTDzwBWvlSIE",
      "Ice": "ChIJnXpQpewn5IgR7k9yxWXUu1M",
      "Stogies": "ChIJlwkiApYn5IgR6XVFMyqLAS4",
      "Rondeazvous": "ChIJkz3V7pUn5IgRQhui26imF1k",
      "Meehan": "ChIJK8NZGZYn5IgRA91RrGETwrQ",
      "Sangrias": "ChIJITcc_ZUn5IgR90iEna6FRGM",
      "NoName": "ChIJA-VeCb4n5IgRmbuF8wdOGaA",
      "StGeorge": "ChIJ4yo36JUn5IgRXgiRD7KMDe0"
    }
}

方法一

locations.js

angular.module('app.locations', [])
  .factory('restsFact', function($http){
    var restaurants = [];

    return {
      getRests: function(){
        return $http.get('locations.json').then(function(response){
          restaurants = response.data.restaurants;
          return restaurants;
        });
      }
    };
  })
  .factory('barsFact', function($http){
    var bars = [];

    return {
      getBars: function() {
        return $http.get('locations.json').then(function(response){
          bars = response.data.bars;
          return bars;
        });
      }
    };
  })
  .service('locationsService', function (ngGPlacesAPI) {
    var x, id, details, push,  placeDetails = [];

    // Takes list of specific type of locations as argument and looks up Place details for each location
    this.details = function(type) {
      for (x in type) {
        if (type.hasOwnProperty(x)) {
          id = type[x];
          ngGPlacesAPI.placeDetails({placeId: id}).then(push);
        }
      }
      return placeDetails;
    };

    push = function (data) {
      details = data;
      placeDetails.push(details);
    };

  });

控制器

.controller('RestCtrl', function($scope, locationsService, restsFact) {

  // Location Details Object
  restsFact.getRests().then(function(locs){
    $scope.restaurants= locationsService.details(locs);
  });

})

//
// Bar Controller
//
.controller('BarsCtrl', function($scope, locationsService, barsFact){

  // Locations Details Object
  barsFact.getBars().then(function(locs){
    $scope.bars = locationsService.details(locs);
  });

})

方法二

使用这种方法我可以加载一个页面,但是如果我移动到下一个页面,我会得到一个错误:[$rootScope:inprog] $digest already in progress。我阅读了错误并了解了为什么会出现错误,但不确定如何修复它。

locations.js

angular.module('app.locations', [])
  .factory('locationsFact', function($http){
    var locations = [];

    return {
      getlocations: function(){
        return $http.get('locations.json').then(function(response){
          locations = response;
          return locations;
        });
      }
    }
  })
  .service('locationsService', function (ngGPlacesAPI) {
    var x, id, details, push,  placeDetails = [];

    // Takes list of specific type of locations as argument and looks up Place details for each location
    this.details = function(type) {
      for (x in type) {
        if (type.hasOwnProperty(x)) {
          id = type[x];
          ngGPlacesAPI.placeDetails({placeId: id}).then(push);
        }
      }
      return placeDetails;
    };

    push = function (data) {
      details = data;
      placeDetails.push(details);
    };

  });

控制器

.controller('locationsCtrl', function($scope, locationsService, locationsFact){

  // Locations Details Object
  locationsFact.getlocations().then(function(locs){
    $scope.restaurants = locationsService.details(locs.data.restaurants);
    $scope.bars = locationsService.details(locs.data.bars);
  });

})

所以上周我读了很多书,也学到了很多东西。我完全重写了上面的乱七八糟的代码,原来它有很多问题。无论如何,我一切正常。这是它现在的样子。

工厂

angular.module('app.factories', [])

  .factory('data', function($http){
    // Get JSON With Place ID's and create array of
    // place id objects for each category
    var places = {};

    places.ids = function(){
      return $http.get('locations.json')
        .success(function(data){
          places.rests = data.restaurants;
          places.bars = data.bars;
          places.lodg = data.lodging;
          places.att = data.attractions;
        });
    };
    return places;
  })

  .factory('details', function(ngGPlacesAPI, $q){
    var details = {};

    // Split ID Array into array of arrays <= 10.
    // Google won't return more than 10 details request at one time.
    details.process = function(type) {
      var idSets = {},
          size = 10,
          i, j, k;

      for (i=0, j=type.length, k=0; i<j; i+=size){
        idSets[k] = type.slice(i, i+size);
        k++;
      }
      return idSets;
    };

    // Lookup Details by Place ID
    // Loop through ID array and return array of details objects
    details.getDetails = function(idSet, pageNum) {
      var page = idSet[pageNum],
          promises = [];

      for(var i=0; i<page.length; i++) {
        promises.push(ngGPlacesAPI.placeDetails({placeId: page[i][i]}));
      }
      return $q.all(promises);
    };

    // Return Details Object
    return details;
  });

控制器

//
// Restaurants Controller
//
.controller('restaurantsCtrl', function(details, data, $scope) {
  var vm = this;

  // Get JSON file with placeIds and set some variables
  data.ids().then(function() {
    var page = details.process(data.rests),
        pageNum = 0,
        numPages = page.length;
    vm.moreData = true;


    // Loads more place details on scroll down
    vm.loadMore = function() {
      if (pageNum <= numPages - 1) {
        pageNum++;
        details.getDetails(page, pageNum).then(function(response) {
          vm.rests.push(response);
          vm.$broadcast('scroll.infiniteScrollComplete');
        });
      }else{vm.moreData=false}
    };

    // Load first page of place details
    details.getDetails(page, pageNum).then(function(response){
      vm.rests = response;
      console.log(vm.rests);
    });

    // Watches for when to load more details
    $scope.$on('$stateChangeSuccess', function(){
      vm.loadMore();
    });

  });
})