「キャッチされていないエラー:[$ 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と関係があります。開発マシンで設定すると、それを再現できます。

回答:


163

リンクをたどると、エラーは$ injectorが依存関係を解決できないことが原因であることがわかります。これは、本番環境でJavaScriptを実行しているときに、JavaScriptが縮小化/醜化/縮小される場合の一般的な問題です。

問題は、たとえばコントローラーがある場合です。

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

ミニファイは変化$scope$q、ランダムな変数に変化します。これは、何を注入するかを角度に伝えません。解決策は、次のように依存関係を宣言することです。

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

これで問題が解決します。

繰り返しますが、私が言ったことはすべて、エラーメッセージが提供するリンクにあります。


2
実際にリンクにアクセスするよう提案してくれてありがとう-私はそれが私の利益のためではなく、内部のアーティファクトだと思っていました。結局のところ、私はすべての依存関係を$injectパブリック変数を介して定義しています。これは、あなたが提案する方法(docs.angularjs.org/guide/diを参照)と同等であると信じています。質問を更新します。
Ken Smith

2
とは言っても、それは明らかに縮小プロセスBundleTable.EnableOptimizations = true;と関係があります。開発マシン()でASP.NET MVC縮小を強制すると、問題を再現できます。見続ける。
ケン・スミス

わかりました。私が忘れていたDIを行っていた別の場所があり、それは縮小プロセスでめちゃくちゃになっていた。ありがとう、これは正しい答えでした。
ケン・スミス

ngminと呼ばれるこれを自動的に処理するパッケージと、ngmin-railsと呼ばれるRailsの対応するgemもあります
ブラッドリーグリフィス2014年

2
@RyanTuck-言い換えると、縮小化されていないコードでは、Angularは関数内の変数名を見て、何を注入する必要があるかを正確に推測できます。しかし、ミニファイされたコードでは、変数名はすべて変更されているため、何を注入するかを知るために、他のメカニズム(コードがミニファイされても変化しないメカニズム)が必要です。ここで、$ inject配列と他のメカニズムが機能します。
Ken Smith、

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'は、1文字の変数名に置き換えられます。これにより、依存関係の角度がわかりません。これを回避するには、関数とともに配列として依存関係名を渡します。

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 Bundleの縮小化を無効にすることができます(バンドル構成ファイルでScriptBundle()の代わりに新しいBundle()を使用してください)。

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、2016

@ Thomas.Benz Bundle()を使用すると、スクリプトの縮小のみが無効になります。ここでの問題は、ScriptBundle()が一部のAngularスクリプトを縮小するときに、関数名を短縮し、その他の関連することを行うことです。そして、Angularがいくつかの内部依存性注入などをしようとすると、それらの名前がカスタムの方法で変更されたため(「SuperController」から「s」など)、適切な関数を見つけることができませんでした。したがって、角度のスクリプトを変更しないままにするか、デフォルトのライブラリではなく他のライブラリを使用して縮小化することをお勧めします。
Schnapz 2016

1

Angular app \ resources \ directivesやその他のファイルを分離している場合は、このようなAngular App Bundleの縮小化を無効にすることができます(バンドル構成ファイルでScriptBundle()の代わりに新しいBundle()を使用してください)。


0

$ http、$ scopeサービスをコントローラー機能に追加します。これらのサービスがない場合は、これらのエラーが発生します。


0

同じ問題がありましたが、別の問題でした。サービスを作成し、$ scopeをパラメーターとして渡しました。
そのリンクのドキュメントが言うように、それはこのエラーを取得する別の方法です:

コントローラーやディレクティブではないもの(サービスなど)にスコープオブジェクトを挿入しようとすると、不明なプロバイダーもスローされます:$ scopeProvider <-$ scopeエラー。これは、コントローラを誤ってサービスとして登録した場合に発生する可能性があります。例:

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.
}]);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.