【问题标题】:AngularJS update view with service/model changes using $q promisesAngularJS 使用 $q 承诺通过服务/模型更改更新视图
【发布时间】:2014-06-19 08:35:01
【问题描述】:

我正在尝试从服务加载数据并使用 $q 更新视图,但它不起作用。如果我将 http 调用放在控制器中,它会起作用,但我希望它成为服务的一部分。

有什么帮助吗?另外,有没有比承诺更好的方法来做到这一点?

下面的演示和代码。

---------Fiddle Demo Link ----------

查看

<div ng-init="getData()">
  <div ng-repeat="item in list">{{item.name}}</div>
</div>

控制器

.controller('ctrl', ['$scope', 'dataservice', '$q', function ($scope, dataservice, $q) {

  $scope.list = dataservice.datalist;

  var loadData = function () {
    dataservice.fakeHttpGetData();
  };

  var setDataToScope = function () {
    $scope.list = dataservice.datalist;
  };

  $scope.getData = function () {
    var defer = $q.defer();
    defer.promise.then(setDataToScope());
    defer.resolve(loadData());
  };

}])

服务

.factory('dataservice', ['$timeout', function ($timeout) {

  // view displays this list at load 
  this.datalist = [{'name': 'alpha'}, {'name': 'bravo'}];

  this.fakeHttpGetData = function () {
    $timeout(function () {

      // view should display this list after 2 seconds
      this.datalist = [{'name': 'charlie'}, {'name': 'delta'}, {'name': 'echo'}];
    },
    2000);
  };

  return this;
}]);

【问题讨论】:

    标签: angularjs promise angular-promise


    【解决方案1】:

    不需要 ngInit 或 $q。你应该这样做。

    您也不应该将dataservice.list 暴露给控制器。这应该是dataservice 私有的,它将包含大部分逻辑来确定是向控制器发送现有列表还是更新列表然后发送它。

    angular.module('app', [])
    
            .controller('ctrl', ['$scope', 'dataservice', function ($scope, dataservice) {
    
                loadData();
    
                function loadData() {
                    dataservice.fakeHttpGetData().then(function (result) {
                        $scope.list = result;
                    });
                }
            }])
    
            .factory('dataservice', ['$timeout', function ($timeout) {
    
                var datalist = [
                    {
                        'name': 'alpha'
                    },
                    {
                        'name': 'bravo'
                    }
                ];
    
                this.fakeHttpGetData = function () {
    
                    return $timeout(function () {
    
                                // Logic here to determine what the list should be (what combination of new data and the existing list).
    
                                datalist =  [
                                    {
                                        'name': 'charlie'
                                    },
                                    {
                                        'name': 'delta'
                                    },
                                    {
                                        'name': 'echo'
                                    }
                                ];
    
                                return datalist;
                            },
                            2000);
                };
    
                return this;
            }]);
    

    【讨论】:

      【解决方案2】:

      首先,不要以这种方式使用ng-init。根据文档:

      ngInit 唯一合适的用途是为特殊属性设置别名 ngRepeat,如下面的演示所示。除了这种情况,你应该 使用控制器而不是 ngInit 来初始化作用域上的值。

      其次,promise 是在这种情况下使用的完美工具,但您无需触摸 $q,因为 $http 调用会为您返回 Promise。

      要正确执行此操作,只需从服务返回 $http 结果:

      this.getDataFromService = function() {
          return $http(/* http call info */);
      };
      

      然后,在你的控制器内部:

      dataservice.getDataFromService().then(function(result){
          $scope.list = result.data;
      });    
      

      这里还有更新的小提琴:http://jsfiddle.net/RgwLR/

      请记住,$q.when() 只是将给定值包装在一个承诺中(在您的示例中模仿来自 $http 的响应)。

      【讨论】:

      • IIRC,http的.then中的结果就是请求本身,你要result.data
      • 是的,但是小提琴没有发出 HTTP 请求,是吗:)?
      • 哦,对了,忘了它增加了一堆额外的东西。
      猜你喜欢
      • 1970-01-01
      • 2014-02-13
      • 2013-12-02
      • 1970-01-01
      • 2018-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-22
      相关资源
      最近更新 更多