Javascript 当装饰angulars$exceptionHandler时,如何防止令人讨厌的副作用?
对于自定义服务器端日志记录,我正在包装angulars$exceptionHandler,就像在许多地方描述的那样,包括stackoverflow和angular文档(有一些变体,但它们基本上做相同的事情): 然而,这导致$exceptionHandler在karma/jasmine单元测试期间不会抛出任何错误 这可以通过使用来解释,当模块未装饰时,它可以正常运行,但当模块为:Javascript 当装饰angulars$exceptionHandler时,如何防止令人讨厌的副作用?,javascript,angularjs,jasmine,karma-runner,Javascript,Angularjs,Jasmine,Karma Runner,对于自定义服务器端日志记录,我正在包装angulars$exceptionHandler,就像在许多地方描述的那样,包括stackoverflow和angular文档(有一些变体,但它们基本上做相同的事情): 然而,这导致$exceptionHandler在karma/jasmine单元测试期间不会抛出任何错误 这可以通过使用来解释,当模块未装饰时,它可以正常运行,但当模块为: beforeEach(module('logging')); describe('$exceptionHandler
beforeEach(module('logging'));
describe('$exceptionHandlerProvider', function () {
// testing standard behaviour of $exceptionHandler
// see https://docs.angularjs.org/api/ngMock/service/$exceptionHandler
it('should capture log messages and exceptions', function () {
module(function ($exceptionHandlerProvider) {
$exceptionHandlerProvider.mode('log');
});
inject(function ($log, $exceptionHandler, $timeout) {
$timeout(function () {
$log.log(1);
});
$timeout(function () {
$log.log(2);
throw 'banana peel';
});
$timeout(function () {
$log.log(3);
});
expect($exceptionHandler.errors).toEqual([]);
expect($log.assertEmpty());
$timeout.flush();
expect($exceptionHandler.errors).toEqual(['banana peel']);
expect($log.log.logs).toEqual([[1], [2], [3]]);
});
});
});
知道如何纠正这种行为吗?还有
我正在使用angular#1.3.14来自
ngMock
的$exceptionHandler
函数具有指向数组的error
属性
装饰程序返回的函数没有该属性:
return function () {
ExceptionLoggingService.apply(null, arguments);
$delegate.apply(null, arguments);
};
例如,这将失败:
expect($exceptionHandler.errors).toEqual([]);
下面是一个有望奏效的实现:
app.config(function($provide) {
$provide.decorator('$exceptionHandler', ['$delegate', 'ExceptionLoggingService',
function($delegate, ExceptionLoggingService) {
var decoratedExceptionHandler = function() {
ExceptionLoggingService.apply(this, arguments);
return $delegate.apply(this, arguments);
};
for (var key in $delegate) {
if (!$delegate.hasOwnProperty(key)) continue;
decoratedExceptionHandler[key] = $delegate[key];
}
return decoratedExceptionHandler;
}
]);
});
作为一个注意事项,你应该始终确保这样做时,装饰。
$exceptionHandler
的实际实现现在可能没有任何属性,但您永远不知道将来是否会有属性。$templateRequest
服务是您必须执行此操作的一个示例,因为它的属性在内部用于使视图动画工作。非常感谢您的出色回答。还有一个小问题。我得到的错误“预期[[1],[2],[TypeError:“undefined”不是一个对象(计算'e.stack.split'),[3]]等于[[1],[2],[3].”我将尝试解决它。没问题:)我刚刚尝试过,它对我有效。您能在Plunk中复制它吗?您能在不调用例外记录服务的情况下尝试吗?我不知道你的实现是什么样子的,只是在测试时使用了一个虚拟的。如果我完全忽略它,这没有什么区别。我创建了一个plunkr,奇怪的是它让其他条件失败,而不是我本地测试中的条件:Removevar args=[].slice.call(arguments)
并将参数
传递给$delegate。改为应用
。
app.config(function($provide) {
$provide.decorator('$exceptionHandler', ['$delegate', 'ExceptionLoggingService',
function($delegate, ExceptionLoggingService) {
var decoratedExceptionHandler = function() {
ExceptionLoggingService.apply(this, arguments);
return $delegate.apply(this, arguments);
};
for (var key in $delegate) {
if (!$delegate.hasOwnProperty(key)) continue;
decoratedExceptionHandler[key] = $delegate[key];
}
return decoratedExceptionHandler;
}
]);
});