强制实施延迟控制器逻辑
Enforce deferring controller logic
我们正在尝试应用John Papa的AngularJS风格指南中列出的准则。
我们开始遵循的规则之一是延迟控制器逻辑:
通过委派给服务和工厂来延迟控制器中的逻辑。
为什么?:当逻辑放置在一个 服务并通过函数公开。
为什么?:在单元测试中,服务中的逻辑可以更容易地隔离, 而控制器中的调用逻辑可以很容易地被模拟。
为什么?:删除依赖项并从 控制器。
这是我们过去将数据检索逻辑放入控制器而不是将其隔离在服务中所违反的。
现在我想让规则尽可能严格。理想情况下,如果其中一个配置的服务作为依赖项传递给控制器,我希望 angular 抛出错误。它是可以在角度级别上解决的问题,还是我应该尝试单独解决它 - 例如,使用自定义ESlint
规则静态解决?
将不胜感激任何见解或提示。
特别是,以下控制器违反了该规则,因为它直接使用$http
服务:
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) {
});
};
}
另外,如果我对代码质量:)过于担心/疯狂,请告诉我
UPD(2015 年 6 月):eslint-plugin-angular
具有内置的ng_no_services
规则,用于强制将延迟控制器逻辑强制实施到服务或工厂。
旧答案。
以下是ESLint
自定义规则,该规则限制名称以 Controller
或 Ctrl
结尾的函数传入任何配置的参数:
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
我可以想象有一些方法可以定义依赖关系,使此特定规则不会发现违规行为,但是,如果您遵循样式指南中建议的建议,它应该对您有用(对我有用)。
我写了一种解决方法,但它是如此棘手和肮脏,以至于永远不能使用它:
<!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>
- 在指令控制器中使用$attrs时出现问题
- 有没有任何方法可以将控制器从文件加载到ui路由器$stateProvider中
- 可以简化嵌套的延迟Q Promises解析吗
- 从控制器返回后Ajax启动事件激发
- 获取@ResponseBody的一部分作为主干和Spring MVC控制器之间的参数
- 如何在单击复选框后调用控制器方法
- 在控制器和数据对象之间同步数据
- Angular.js延迟控制器初始化
- 强制实施延迟控制器逻辑
- AngularJS 1.2.0:延迟加载控制器和模板
- 延迟控制器执行,直到分配了 rootScope 属性的值
- 如何在对 AngularJS 控制器进行单元测试时模拟网络延迟
- 使用ocLazyLoad延迟加载带有$stateProvider的控制器
- 从服务到控制器的角度传递延迟错误
- 在执行服务之后延迟控制器初始化
- AngularJS:延迟加载控制器和内容
- Angular JS延迟控制器和指令的初始化,直到数据从服务器返回
- angularjs在解析延迟加载脚本和分别添加视图控制器时会抛出Error: [ng:areq]
- 延迟页控制器的执行,直到收集到初始化数据
- 我应该如何延迟加载ExtJS MVC控制器、视图、存储和模型