2015-06-17 75 views
0

我想問/討論這是好還是不好的做法 - 做一個服務調用的優點和缺點使控制器儘可能乾淨和短。換句話說:不再有回調,而是利用Angular的Angular綁定原則。解決承諾在服務中沒有控制器回調

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

我想達到什麼樣的被註釋掉的Plnkr>$scope.data = DataService.getData(3);線42。

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

我最好的問候服務請求數據並返回承諾的做法是:

  • 回報承諾在控制器(在DataService的,返回deferred.promise)
  • ,調用DataService.getData (3)。然後()

所以我不會傳遞一個回調到使用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

你想在控制器中實現的另一件事,是處理的DataService的錯誤。通常你會想告訴用戶有關錯誤(==鏈接到UI元素的數據),並且應該在控制器中完成。所以這是一個贊成返回承諾(而不是傳遞迴調)的贊成。 –

+0

會接受這個引導我向正確方向的引導者。一些關於UI操作的個人反饋:不要在控制器中需要這些東西,這些東西需要通過指令來處理(儘可能多)。 –

+0

仍然有一個問題仍然存在,那就是關於鏈接承諾,我寧願在服務器和控制器之前完成這些工作,以免後者陷入混亂。你對此有何想法? –

1

AFAIK這是不可能的 - 看到這個Thread

可以「自動」解決使用角路線的承諾。解決的承諾將被注入到您的控制器中。

+0

不錯,我喜歡(乾淨)解決方案,但是這是一個可以在運行時調用的服務,而不是在構建視圖初始化時。不過好點。 –

+0

角色路由狀態是在配置生命週期中定義的,但承諾將在運行時解除 – Michael

+0

我的意思是在單擊按鈕(例如從UI)調用服務時。角度路線不幫我的權利? –

-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="[email protected]"></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> 
+0

這是我分叉的原始plnkr,根據我的描述,這正是我不想找的東西。 –

相關問題