如何将数据从服务传递到控制器?

时间:2015-07-11 05:05:23

标签: json angularjs controller ionic-framework factory

好的,现在我正在搞乱离子框架并同时学习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);
})

2 个答案:

答案 0 :(得分:2)

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

首先,您在}定义后额外SpecialService

SpecialService

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

这不会是因为你的GetData.getSpecials()什么都不返回。

如果您要修复GetData.getSepcials返回:

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;
   });

另外,正如马特指出的那样,在你的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;
    });
}

答案 1 :(得分:0)

看起来你有点过于复杂化了。你没有明确的理由在工厂周围传递数据。我认为这三家工厂可以合二为一。也许尝试像..

<强>的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!");
        });
    }

  }

});