但是我对如何在提供者内部传递实际的$delegate并返回到装饰器感到困惑。
我正在尝试装饰angularjs中的$log服务,以便通过http将日志发送到后端。我设法做到了这一点,使用这样的东西:
app.config(['$provide', function ($provide) {
$provide.decorator('$log', ['$delegate', loggerDecorator]);
}]);
var loggerDecorator = function ($delegate) {
...decorating logic
$delegate.log = prepareLogFn($delegate.log);
return $delegate;
}
这很好,但是,我更愿意使用提供者作为装饰器,以便我可以在模块的配置阶段配置它,用于设置分隔符,远程api url等。
我尝试创建一个像这样的提供者:
angular.module('mods.logging').factory(serviceId, [backendLoggingDecorator]);
function backendLoggingDecorator() {
var remoteUri = '';
return {
setRemoteUri: function (uri) {
remoteUri = uri;
},
$get: function ($delegate) {
var ajaxLogger = log4javascript.getLogger();
var ajaxAppender = new log4javascript.AjaxAppender(remoteUri);
ajaxAppender.setThreshold(log4javascript.Level.ALL);
ajaxLogger.addAppender(ajaxAppender);
function prepareLogFn(loggingFunc) {
return function () {
if (ajaxLogger) ajaxLogger.info(arguments);
loggingFunc.apply(null, args);
};
}
$delegate.log = prepareLogFn($delegate.log);
return $delegate;
}
};
}
,然后执行如下操作:
app.config(['$provide', function ($provide) {
$provide.decorator('$log', ['backendLoggingDecorator', function(bld) {
return bld;
}]);
}]);
这里有一个例子。在enhanceLogging
函数中,您可以对日志做任何事情,用额外的信息装饰它,将其发布到外部服务等。
var myApp = angular.module('myApp', []).provider('logEnhancer', [function () {
this.$get = function () {
return {
enhanceAngularLog: function ($log) {
$log.getInstance = function (context) {
return {
log: enhanceLogging($log.log, context, 'log'),
info: enhanceLogging($log.info, context, 'info'),
warn: enhanceLogging($log.warn, context, 'warn'),
debug: enhanceLogging($log.debug, context, 'debug'),
error: enhanceLogging($log.error, context, 'error')
};
}
function enhanceLogging(loggingFunc, context, level) {
return function () {
var modifiedArguments = [].slice.call(arguments);
modifiedArguments[0] = moment().format('dddd h:mm:ss a') + ' || ' + modifiedArguments[0] + ' || from Ctrl: ' + context;
loggingFunc.apply(null, modifiedArguments);
};
}
}
};
};
}]).run(['$log', 'logEnhancer', function ($log, logEnhancer) {
logEnhancer.enhanceAngularLog($log);
}]).controller('LogCtrl', ['$log', '$scope', function ($log, $scope) {
var $log = $log.getInstance('LogCtrl');
$scope.doTest = function () {
$log.debug("This *will* appear in your console");
};
}]);
<script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.1/moment.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="LogCtrl">
<h3>Enhance $log service</h3>
<button ng-click="doTest()">test logger</button>
<p>Look the console for the modified <code>$log.debug()</code> message.</p>
</div>