在没有控制器回调的情况下解决服务中的承诺

时间:2015-06-17 14:03:20

标签: angularjs callback controller promise angular-promise

我想问/讨论这是好的还是坏的做法 - 做出服务电话的利弊是什么让控制器尽可能干净和短暂。换句话说:不再使用回调,而是使用Angular的Angular绑定原则。

看看我分叉的Plnkr: http://plnkr.co/edit/zNwy8tNKG6DxAzBAclKY

我想实现Plnkr第42行注释的内容> $scope.data = DataService.getData(3);

app.factory('DataService', function($q, $http) {
      var cache = {};
      var service= {
        data:{src:''},
        getData: function(id, callback) {
          var deffered = $q.defer();
          if (cache[id]) {
            service.data.src = 'cache';
            deffered.resolve(cache[id])
          } else {
            $http.get('data.json').then(function(res) {
              service.data.src = 'ajax';
              cache[id] = res.data;
              cache[id].dataSource = service.data.src;
              deffered.resolve(cache[id])
            })
          }
          return deffered.promise.then(callback);
        }
      }
      return service
    })
     app.controller('MainCtrl', function($scope, DataService) {

        DataService.getData(3, function(result) {
          $scope.data = result;
        });

     //$scope.data = DataService.getData(3);
});

3 个答案:

答案 0 :(得分:3)

关于请求数据和返回承诺的服务,我的最佳做法是:

  • 返回一个promise(在DataService中,返回deferred.promise)
  • 在控制器中,调用DataService.getData(3).then(,)

所以我不会将回调传递给使用promise的服务函数。

更难的问题是服务功能应该做什么,以及then(function(data) {...})应该做什么。以下是一些指导原则:

  • 共享的任何内容(数据/重复功能),在服务中实现
  • 与将数据/函数绑定到UI元素相关的任何内容,在控制器中实现
  • 让控制器尽可能简单 - 它们应该只链接UI元素和模型。
  • 任何模型逻辑,处理,格式解析等 - 在服务中实现

我在阅读评论后添加了这部分内容:

如果您需要进行一些处理(比如检查缓存结果,解析结果等),那么在服务中执行此操作的适当位置。

所以我会修改你的代码如下:

var service= {
  data:{src:''},
  getData: function(id) {
    var deffered = $q.defer();
    if (cache[id]) {
      service.data.src = 'cache';
      deffered.resolve(cache[id]);
      return deferred;
    } else {
      return $http.get('data.json').then(function(res) {
        service.data.src = 'ajax';
        cache[id] = res.data;
        cache[id].dataSource = service.data.src;
        return cache[id]; // this will resolve to the next ".then(..)"
      });
    }
  }
}

答案 1 :(得分:1)

虽然这是不可能的 - 请参阅此Thread

你可以自动'通过使用angular-route解决这个问题。已解决的承诺将被注入您的控制器。

答案 2 :(得分:-1)

你可以这样做plunker

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

<head>
  <meta charset="utf-8" />
  <title>AngularJS Plunker</title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link href="style.css" rel="stylesheet" />
  <script data-semver="1.2.4" src="http://code.angularjs.org/1.2.4/angular.js" data-require="angular.js@1.2.x"></script>
  <script src="app.js"></script>
  <script>
    app.factory('DataService', function($q, $http) {
      var cache = {};
      var service= {
        data:{src:''},
        getData: function(id, callback) {
          var deffered = $q.defer();
          if (cache[id]) {
            service.data.src = 'cache';
            deffered.resolve(cache[id])
          } else {
            $http.get('data.json').then(function(res) {
              service.data.src = 'ajax';
              cache[id] = res.data;
              cache[id].dataSource = service.data.src;
              deffered.resolve(cache[id])
            })
          }
          return deffered.promise;
        }
      }
      return service
    })
     app.controller('MainCtrl', function($scope, DataService) {

         DataService.getData(3).then(function (data) {
          $scope.data = data;
        });
    });
  </script>
</head>

<body ng-controller="MainCtrl">

<div>Source: {{data.dataSource}}</div>
  <pre>{{data}}</pre>
</body>

</html>