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