【问题标题】:How can I pass data from a service into my controller?如何将数据从服务传递到我的控制器?
【发布时间】:2015-07-11 05:05:23
【问题描述】:

好的,现在我正在搞乱 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);
})

【问题讨论】:

  • 我不确定我是否理解您的 SpecialService 的意义。为什么不直接将 GetData 服务注入控制器并直接调用 getSpecials 方法?
  • 因为我有两个控制器需要获取相同的数据,所以如果我这样做,那么我需要为另一个控制器重复代码。

标签: json angularjs controller ionic-framework factory


【解决方案1】:

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

首先,在您的 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;
    });
}

【讨论】:

  • 感谢您提供详细信息!我想我现在更了解 Promise 的工作原理了。
【解决方案2】:

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

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

  }

});

【讨论】:

  • 如果只有一个控制器就好了。我需要能够将数据传递给另一个控制器,这就是我有另一个服务的原因。在没有这么多服务但仍然能够共享数据的情况下,是否有解决方法?
  • 我没有看到问题。只需将服务也注入另一个控制器。工厂是单例的,因此所有控制器都可以使用一个实例。
  • 哇,我真的把一切都复杂化了。谢谢!
猜你喜欢
  • 2017-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多