4

我們正在嘗試應用John Papa的AngularJS Style Guide中列出的準則。強制推遲控制器邏輯

其中一個,我們就開始遵循的規則是Defer Controller Logic

Defer logic in a controller by delegating to services and factories.

Why?: Logic may be reused by multiple controllers when placed within a service and exposed via a function.

Why?: Logic in a service can more easily be isolated in a unit test, while the calling logic in the controller can be easily mocked.

Why?: Removes dependencies and hides implementation details from the controller.

這事通過將數據檢索邏輯到控制器中,而不是在服務隔離它,我們已經在過去的侵犯。

現在我想使規則儘可能嚴格。理想情況下,如果其中一個配置的服務作爲依賴項傳遞給控制器​​,我希望角度引發錯誤。它是可以在角度水平上解決的問題,還是我應該嘗試單獨解決 - 例如,靜態地使用自定義規則ESlint

希望得到任何見解或提示。


特別是以下控制器違反了規則,因爲它使用$http service直接:

function OrderController($http, $q, config, userInfo) { 
    var vm = this; 
    vm.checkCredit = checkCredit; 
    vm.isCreditOk; 

    function checkCredit() { 
     var settings = {}; 

     return $http.get(settings) 
      .then(function(data) { 
       vm.isCreditOk = vm.total <= maxRemainingAmount; 
      }) 
      .catch(function(error) { 

      }); 
    }; 
} 

另外,讓我知道如果我越來越過分關注/瘋狂的代碼質量: )

+0

我會嘗試使用ESLint並使用防止在控制器中使用$ http/$資源的規則。我個人認爲你應該在你的開發團隊中進行交談,並且在處理數據時讓每個人都在同一頁面上。 –

回答

4

UPD(2015年6月):eslint-plugin-angular內置了ng_no_services規則強制執行推遲控制器邏輯服務或工廠。


舊的回答。

這裏是限制的函數,其名稱與ControllerCtrl結束時,有任何的傳入的配置參數的ESLint custom rule

module.exports = function (context) { 

    "use strict"; 

    var restrictedParams = context.options[0] || []; 

    var check = function (node) { 
     var name = node.id && node.id.name; 

     if (/(Controller|Ctrl)$/.test(name) && node.params) { 
      var params = node.params.map(
       function (param) { 
        return param.name; 
       } 
      ); 

      restrictedParams.filter(function (n) { 
       if (params.indexOf(n) != -1) { 
        context.report(node, "This controller function uses a restricted dependency {{param}}.", { 
         param: n 
        }); 
       } 
      }); 

     } 
    }; 

    return { 
     "FunctionDeclaration": check, 
     "FunctionExpression": check 
    } 
}; 

實施例的配置(eslint.json):

{ 
    "env": { 
    "browser": true, 
    "node": true, 
    "jasmine": true 
    }, 
    "globals": { 
    "angular": true, 
    "browser": true, 
    "element": true, 
    "by": false, 
    "inject": false 
    }, 
    "plugins": [ 
    "angularjs" 
    ], 
    "rules": { 
    "ctrl-logic": [2, ["$http"]] 
    } 
} 

現在,想象我定義了以下控制器(違反規則):

angular 
    .module("app") 
    .controller("AppController", AppController); 


AppController.$inject = ["$scope", "ConnectionService", "ConfigService", "StatusService", "$http"]; 

function AppController($scope, ConnectionService, ConfigService, StatusService, $http) { 
    ... 
} 

如果我運行eslint檢查會報告錯誤:

$ grunt lint 
Running "eslint:target" (eslint) task 

app/app-controller.js 
    8:0 error This controller function uses a restricted dependency $http ctrl-logic 

✖ 1 problem 

我能想象有辦法來定義的方式,這個特殊的規則不會發現違反依賴關係,但是,如果你遵循風格指南中建議的建議,它應該適合你(爲我工作)。

2

我已經寫了一種解決方法,但它如此棘手,骯髒,它不能永遠使用:

<!doctype html> 
 
<html> 
 
    <head> 
 
     <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.js"></script> 
 
    </head> 
 
    <body ng-app="plunker" ng-controller="MainCtrl"> 
 
     <div ng-repeat="violation in codestyleViolations"> 
 
      {{violation}} 
 
     </div> 
 
    </body> 
 
    <script> 
 
    var app = angular.module('plunker', []).config(function($controllerProvider) { 
 
     $controllerProvider.$get[0] = 'trickyInjector'; 
 
    }).factory('trickyInjector', ['$injector', '$rootScope', function($injector, $rootScope) { 
 
     $rootScope.codestyleViolations = []; 
 
     var originalFunc = $injector.invoke; 
 
     $injector.invoke = function(fn, self, locals, serviceName) { 
 
      if (locals && locals.$scope && fn.indexOf('$http') !== -1) { 
 
       $rootScope.codestyleViolations.push('ALYARM! ' + serviceName + ' uses $http'); 
 
      } 
 
      return originalFunc.apply(this, arguments); 
 
     }; 
 
     return $injector; 
 
    }]).controller('MainCtrl', ['$scope', '$http', function($scope, $http) { 
 

 
    }]); 
 
    </script> 
 
</html>

+0

我喜歡你的「永遠不要使用」:D謝謝! – alecxe