部署后出现“未捕获的错误:[$ injector:unpr]”


97

我有一个相当简单的Angular应用程序,可以在我的开发机上正常运行,但是在部署它后却出现此错误消息(在浏览器控制台中)失败:

Uncaught Error: [$injector:unpr] http://errors.angularjs.org/undefined/$injector/unpr?p0=tProvider%20%3C-%20t%20%3C-%20%24http%20%3C-%20%24compile

除此之外,没有其他消息。页面首次加载时会发生这种情况。

我正在运行ASP.NET MVC5,Angular 1.2RC3,并通过git推送到Azure。

谷歌搜索还没有发现任何有趣的东西。

有什么建议?

编辑:

我正在使用TypeScript,并使用$inject变量定义依赖项,例如:

export class DashboardCtrl {

    public static $inject = [
        '$scope',
        '$location',
        'dashboardStorage'
    ];

    constructor(
        private $scope: IDashboardScope,
        private $location: ng.ILocationService,
        private storage: IDashboardStorage) {
    }
}

我认为应该(或打算)解决在最小化期间​​出现的可能导致此错误的局部变量重命名问题。

就是说,这显然与缩小过程有关,因为当我BundleTable.EnableOptimizations = true在开发机上设置时,就可以复制它。

Answers:


163

如果您单击链接,它将告诉您该错误是由于$ injector无法解析您的依赖关系而导致的。当javascript最小化/丑化/无论您要对其进行生产时,这是angular的常见问题。

问题是当您有一个控制器时。

angular.module("MyApp").controller("MyCtrl", function($scope, $q) {
  // your code
})

缩小更改$scope$q变成随机变量,该变量不会告诉angular要注入什么。解决方案是这样声明您的依赖项:

angular.module("MyApp")
  .controller("MyCtrl", ["$scope", "$q", function($scope, $q) {
  // your code
}])

那应该解决您的问题。

重申一下,我所说的只是错误消息提供给您的链接。


2
感谢您提出实际访问该链接的建议-我认为这是一些内部工件,而不是出于我的利益。事实证明,我正在通过$inject公共变量定义我的所有依赖关系,我相信这与您建议的方式相同(请参阅docs.angularjs.org/guide/di)。我将更新我的问题。
肯·史密斯

2
就是说,这显然与缩小过程有关,因为当我在开发机(BundleTable.EnableOptimizations = true;)上强制ASP.NET MVC缩小时,我可以重现该问题。继续看。
肯·史密斯

好,知道了。我在做DI时忘了另一个地方,在缩小过程中变得一团糟。谢谢,这是正确的答案。
肯·史密斯

还有一个可以自动为您处理的软件包,称为ngmin,还有一个对应于Rails的gem,名为ngmin-rails
bradleygriffith 2014年

2
@RyanTuck-换句话说,使用未缩略的代码,Angular可以仅查看函数中的变量名称,并对需要注入的内容进行很好的猜测。但是对于缩略的代码,变量名称都杂乱无章,因此还需要其他一些机制(知道代码变小时不会改变的机制)来知道要注入什么。这就是$ inject数组和其他机制起作用的地方。
肯·史密斯

13

我自己遇到了同样的问题,但是我的控制器定义看起来与上面的有所不同。对于这样定义的控制器:

function MyController($scope, $http) {
    // ...
}

只需在声明之后添加一行,以指示在实例化控制器时要注入的对象:

function MyController($scope, $http) {
    // ...
}
MyController.$inject = ['$scope', '$http'];

这使其具有缩小安全性。


11

当控制器或指令未指定为依赖项和函数的数组时,会发生此问题。例如

angular.module("appName").directive('directiveName', function () {
    return {
        restrict: 'AE',
        templateUrl: 'calender.html',
        controller: function ($scope) {
            $scope.selectThisOption = function () {
                // some code
            };
        }
    };
});

最小化时,传递给控制器​​功能的'$ scope'被单个字母变量name代替。这将使角度线索毫无依赖性。为避免这种情况,将依赖项名称与函数一起作为数组传递。

angular.module("appName").directive('directiveName', function () {
    return {
        restrict: 'AE',
        templateUrl: 'calender.html'
        controller: ['$scope', function ($scope) {
            $scope.selectThisOption = function () {
                // some code
            };
        }]
    };
});

10

如果您已为angular app \ resources \ directives和其他内容分离了文件,则可以像这样禁用您的angular app包的缩小(在包配置文件中使用new Bundle()而不是ScriptBundle()):

bundles.Add(
new Bundle("~/bundles/angular/SomeBundleName").Include(
               "~/Content/js/angular/Pages/Web/MainPage/angularApi.js",
               "~/Content/js/angular/Pages/Web/MainPage/angularApp.js",
               "~/Content/js/angular/Pages/Web/MainPage/angularCtrl.js"));

角度应用程序将在未修改的捆绑中出现。


关于性能,哪个更好?Bundle()或ScriptBundle()?
Thomas.Benz

@ Thomas.Benz使用Bundle()只会禁用脚本的缩小功能。这里的问题是,当ScriptBundle()缩小某些Angular脚本时,它会缩短函数名称并执行其他相关操作。当Angular尝试进行一些内部依赖注入或类似的操作时,它找不到适合的函数,因为它们的名称已以自定义方式更改(例如从“ SuperController”更改为“ s”)。因此,最好不要修改角度脚本,或者尝试使用其他一些库进行压缩,而不是使用默认库。
Schnapz '16

1

如果您已为angular app \ resources \ directives和其他内容分离了文件,则可以像这样禁用您的angular app包的缩小(在包配置文件中使用new Bundle()而不是ScriptBundle()):



0

我遇到了同样的问题,但是问题是不同的,我试图创建一个服务并将$ scope作为参数传递给它。
这是获取此错误的另一种方法,因为该链接的文档说:

试图将范围对象注入非控制器或指令(例如服务)之外的任何对象,也会引发Unknown provider:$ scopeProvider <-$ scope error。如果有人错误地将控制器注册为服务,例如:

angular.module('myModule', [])
       .service('MyController', ['$scope', function($scope) {
        // This controller throws an unknown provider error because
        // a scope object cannot be injected into a service.
}]);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.