我仍然想知道如何在我们的源代码中找到导致此问题的地方,但是我现在已经能够手动找到问题了。
全局作用域上声明了一个控制器函数,而不是在应用模块上使用.controller()
调用。
因此类似于这样:
function SomeController( $scope, i18n ) { }
这对于AngularJS来说很好用,但为了让代码混淆后仍然能正常运行,我不得不将其修改为:
var applicationModule = angular.module( "example" );
function SomeController( $scope, i18n ) { }
applicationModule.controller( "SomeController", [ "$scope", "i18n", SomeController ] );
经过进一步的测试,我实际上发现了更多控制器引起问题的情况。这就是我手动找到它们的方法:
首先,我认为在uglify选项中启用输出美化非常重要。对于我们的grunt任务,这意味着:
options : {
beautify : true,
mangle : true
}
我随后在Chrome中打开了项目网站,并打开了DevTools。这导致类似下面这样的错误被记录:
![enter image description here](https://istack.dev59.com/LMZNj.webp)
我们感兴趣的调用堆栈中的方法是我标记的那个箭头所指向的,它是injector.js
中的providerInjector
。您需要在它抛出异常的地方设置断点:
![enter image description here](https://istack.dev59.com/xatRx.webp)
现在重新运行应用程序时,将会触发断点,您可以跳转到调用堆栈的上方。其中有一个来自injector.js
中的invoke
的调用,可从“Incorrect injection token”字符串中识别出:
![enter image description here](https://istack.dev59.com/EWjtx.webp)
locals
参数(在我的代码中转换为d
)可以很好地指出源代码中的哪个对象存在问题:
![enter image description here](https://istack.dev59.com/xaKAi.webp)
在我们的源代码上执行快速的grep
,找到许多modalInstance
实例,但从那里开始,很容易就能找到源代码中的这个位置:
var ModalCreateEditMeetingController = function( $scope, $modalInstance ) {
};
必须更改为:
var ModalCreateEditMeetingController = [ "$scope", "$modalInstance", function( $scope, $modalInstance ) {
} ];
如果变量没有包含有用信息,您还可以跳转到堆栈的更高层,这时您应该会遇到调用invoke
的地方,它应该会提供额外的提示:
![图像描述](https://istack.dev59.com/z1qYk.webp)
防止再次发生
现在您已经找到了问题,我认为我应该提一下如何最好地避免将来再次出现这种情况。
显然,您可以在每个地方都使用内联数组注释,或者(根据您的喜好)$inject
属性注释,并尽量不要忘记。如果您这样做,请确保启用严格依赖项注入模式,以尽早捕获此类错误。
注意!如果您正在使用Angular Batarang,则StrictDI可能无法正常工作,因为Angular Batarang会将未注释的代码注入到您的代码中(坏Batarang!)。
或者您可以让ng-annotate来处理它。我强烈推荐这样做,因为它可以消除此区域中出现的大量潜在错误,例如:
保持注释更新只是一件麻烦事,如果可以自动完成,就没有必要这样做。ng-annotate正是如此。
它应该与grunt-ng-annotate和gulp-ng-annotate非常好地集成到您的构建过程中。