angularjs - 如何使用提供者而不是函数来装饰 $log 服务

标签 angularjs angular-decorator

我正在尝试在 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;
    }]);
}]);

但我对如何在提供程序内部传递实际的 $delegate 并返回到装饰器感到困惑。

最佳答案

这里有一个例子。在 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>

关于angularjs - 如何使用提供者而不是函数来装饰 $log 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22411609/

相关文章:

angularjs - 带有对象数组的 Angular Material md-switch

javascript - 使用 Angular 指令使用 element.bind(event, function) 调整触发器上文本区域的大小

javascript - NG-Grid 制作全屏

angular - 为什么 Angular 2 使用装饰器?

angular - Angular 组件类如何实例化?

javascript - 从日期时间日历更改月份名称(输出)

angularjs - 在 ASP.NET MVC 中使用 Angular data-ng-model 时 HTML 控件无法正常工作

Angular 6 : Adding @Input to component doesn't work

angular - 如何更新依赖注入(inject) token 值

angular - 如何在不出现错误 : Class is using Angular features but is not decorated. 的情况下实现 OnInit 请添加显式 Angular 装饰器