如何将服务中的数据传递到我的控制器中?

How can I pass data from a service into my controller?

好吧,现在我正在摆弄 ionic 框架并同时学习 angularJS。我刚刚遇到 $q 和异步调用,但我似乎无法正确处理。我希望能够解析我已经使用 GetJsonSpecials 设置的 JSON 文件,然后将其传递给 GetData,然后再将其传递给我的控制器 SpecialsCtrl 所以我可以将其附加到 $scope。我知道我没有正确理解承诺,因为 SpecialService 中的所有内容都未定义。我可以从其他两个服务中完美地获取数据,但是当我尝试将它传递给 SpecialService 时,它似乎都崩溃了,这反过来在我的控制器中最终成为未定义的。也许我没有以正确的方式解决这个问题?做这种事情有什么最佳实践吗?

angular.module('starter.controllers', [])

.controller('SpecialsCtrl', function ($scope, SpecialService) {
  $scope.specials = SpecialService.all();
  console.log("Specials Controller: Got Data", $scope.specials);
})

//Create methods to access the specials inside the controller in which we inject this in
.factory('SpecialService', function (GetData) {
  var specials = GetData.getSpecials();
  console.log("DATAAAA: ", specials);
    return {
      // Return all specials
      all: function () {
        console.log("Inside return with specials: ", specials);
        return specials;
      },
      getSpecialWithId : function (specialId) {
         // Simple index lookup
         return specials[i];
      }
    }
  }
})

.factory('GetData', function(GetJsonSpecials) {
  return {
    getSpecials : function() {
      GetJsonSpecials.retrieveData().then(function (data) {
        console.log("Got the JSON data", data);
        return data;
      }, function (status) {
        alert("Error getting specicals", status);
        console.log("Error getting specicals", status);
      });
    }
  }
})
//Asynchronously get the specials from the json file
.factory('GetJsonSpecials', function ($q, $http) {
  return {
    retrieveData : function() {
      var deferred = $q.defer();
      $http.get('js/specials.json').success(function (data, status) {
        deferred.resolve(data);
      }).error(function (status) {
        deferred.reject(status);
        console.log("Error in handling json!");
      });
      return deferred.promise;
    }
  }
})

我之所以过于复杂,是因为最后我希望能够将数据共享到另一个控制器,该控制器将在新视图中显示特定特价商品的属性。

.controller('DetailCtrl', function ($scope, $stateParams, JsonSpecials, $firebaseAuth) {
  $scope.id = parseInt($stateParams.specialId);
  $scope.special = JsonSpecials.getSpecialWithId($scope.id);
})

看来你把事情复杂化了一点。您无缘无故地在工厂周围传递数据。我认为这三个工厂可以合并为一个。也许尝试像..

index.html

<!DOCTYPE html>
<html ng-app="foobar">

  <head>
    <link rel="stylesheet" href="style.css">

  </head>

  <body>

    <div ng-controller="SpecialsCtrl">
      {{specials}}
    </div>

    <div ng-controller="AnotherController">
      {{specials}}
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
    <script src="script.js"></script>
  </body>

</html>

script.js

angular.module('foobar', [])

.controller('SpecialsCtrl', function ($scope, JsonSpecials) {

  JsonSpecials.retrieveData().then(function(data){
    $scope.specials = data;
  });

})

.controller('AnotherController', function ($scope, JsonSpecials) {

  JsonSpecials.retrieveData().then(function(data){
    $scope.specials = data;
  });

})


//$http returns a promise anyway so you don't need $q
.factory('JsonSpecials', function ($http){


  return {

    retrieveData : function() {
      return $http
        .get('js/specials.json')
        .error(function (status) {
          console.log("Error in handling json!");
        });
    }

  }

});

这里有一些问题。主要问题是 angularjs promises 是异步的,而您正试图以同步方式使用它们。

首先,您的 SpecialService 定义后有一个额外的 }

在你的 SpecialService:

.factory('SpecialService', function (GetData) {
   var specials = GetData.getSpecials();

这没什么,因为你的GetData.getSpecials()return什么都没有。

如果您要将 GetData.getSepcials 修复为 return:

getSpecials : function() {
  return GetJsonSpecials.retrieveData().then(function (data) {
    console.log("Got the JSON data", data);
    return data;
  }, function (status) {
    alert("Error getting specicals", status);
    console.log("Error getting specicals", status);
  });
}

然后回到 SpecialService,您需要更改获取数据的方式。

var specials = GetData.getSpecials();

也不会给你你的数据。这将是一个承诺,因为它是异步的。所以需要

  GetData.getSpecials().then(function(data) {
    return data;
   });

此外,正如 Matt 所指出的,在您的 retrieveData 定义中,您正在创建一个不必要的承诺。所以

retrieveData : function() {
  var deferred = $q.defer();
  $http.get('js/specials.json').success(function (data, status) {
    deferred.resolve(data);
  }).error(function (status) {
    deferred.reject(status);
    console.log("Error in handling json!");
  });
  return deferred.promise;
}

等同于:

retrieveData : function() {
    return $http.get('js/specials.json').error(function (status) {
        console.log("Error in handling json!");
        return status;
    });
}