"Nicht erfasster Fehler: [$ Injektor: unpr]" mit Winkel nach dem Einsatz

97

Ich habe eine ziemlich einfache Angular-Anwendung, die auf meinem Entwicklungscomputer einwandfrei ausgeführt wird, aber nach der Bereitstellung mit dieser Fehlermeldung (in der Browserkonsole) fehlschlägt:

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

Keine andere Nachricht außer dem. Dies geschieht beim ersten Laden der Seite.

Ich verwende ASP.NET MVC5, Angular 1.2RC3 und pushe über Git auf Azure.

Googeln hat nichts Interessantes ergeben.

Irgendwelche Vorschläge?

BEARBEITEN:

Ich verwende TypeScript und definiere meine Abhängigkeiten mit der $injectVariablen, z.

export class DashboardCtrl {

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

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

Ich bin der Meinung, dass dies die Probleme beim Umbenennen lokaler Variablen umgehen sollte (oder soll), die während der Minimierung auftreten und diesen Fehler verursachen können.

Das heißt, es hat eindeutig etwas mit dem Minimierungsprozess zu tun, da BundleTable.EnableOptimizations = trueich es reproduzieren kann , wenn ich es auf meinem Entwicklungscomputer einstelle .

Ken Smith
quelle

Antworten:

163

Wenn Sie Ihrem Link folgen, wird Ihnen mitgeteilt, dass der Fehler darauf zurückzuführen ist, dass der $ -Injektor Ihre Abhängigkeiten nicht auflösen kann. Dies ist ein häufiges Problem bei Angular, wenn das Javascript minimiert / hässlich wird / was auch immer Sie für die Produktion damit machen.

Das Problem ist, wenn Sie zB einen Controller haben;

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

Die Verkleinerungs Veränderungen $scopeund $qin Zufallsvariablen , die sagen , nicht eckig , was zu injizieren. Die Lösung besteht darin, Ihre Abhängigkeiten wie folgt zu deklarieren:

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

Das sollte dein Problem beheben.

Um es noch einmal zu wiederholen, alles, was ich gesagt habe, befindet sich unter dem Link, den die Fehlermeldung für Sie bereitstellt.

Stuart Nelson
quelle
2
Vielen Dank für den Vorschlag, den Link tatsächlich zu besuchen. Ich hatte angenommen, dass es sich um ein internes Artefakt handelt, das nicht zu meinem Vorteil ist. Wie sich herausstellt, definiere ich alle meine Abhängigkeiten über die $injectöffentliche Variable, die meiner Meinung nach der von Ihnen vorgeschlagenen entspricht (siehe docs.angularjs.org/guide/di ). Ich werde meine Frage aktualisieren.
Ken Smith
2
Das heißt, es hat eindeutig etwas mit dem Minifizierungsprozess zu tun, da ich BundleTable.EnableOptimizations = true;das Problem reproduzieren kann , wenn ich ASP.NET MVC-Minifizierungen auf meinem Entwicklungscomputer erzwinge ( ). Weiter schauen.
Ken Smith
OK, habe es herausgefunden. Es gab einen anderen Ort, an dem ich DI machte, den ich vergessen hatte, und der im Minifizierungsprozess durcheinander kam. Danke, das war die richtige Antwort.
Ken Smith
Es gibt auch ein Paket namens ngmin , das dies automatisch für Sie erledigt, und ein entsprechendes Juwel für Rails namens ngmin-Rails .
Bradleygriffith
2
@RyanTuck - Mit anderen Worten, mit nicht minimiertem Code kann Angular einfach die Variablennamen in Ihren Funktionen anzeigen und eine gute Vermutung darüber anstellen, was injiziert werden muss. Bei verkleinertem Code werden jedoch alle Variablennamen munged, sodass ein anderer Mechanismus erforderlich ist - ein Mechanismus, der sich nicht ändert, wenn der Code minimiert wird -, um zu wissen, was injiziert werden soll. Hier kommen das $ injiz-Array und die anderen Mechanismen ins Spiel.
Ken Smith
13

Ich bin selbst auf dasselbe Problem gestoßen, aber meine Controller-Definitionen sahen etwas anders aus als oben. Für Controller, die wie folgt definiert sind:

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

Fügen Sie nach der Deklaration einfach eine Zeile hinzu, die angibt, welche Objekte beim Instanziieren des Controllers injiziert werden sollen:

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

Dies macht es minifizierungssicher.

Matt
quelle
11

Dieses Problem tritt auf, wenn der Controller oder die Direktive nicht als Array von Abhängigkeiten und Funktionen angegeben sind. Beispielsweise

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

Bei Minimierung Der an die Controller-Funktion übergebene '$ scope' wird durch einen Variablennamen mit einem Buchstaben ersetzt. Dies macht die Abhängigkeit ahnungslos. Um dies zu vermeiden, übergeben Sie den Abhängigkeitsnamen zusammen mit der Funktion als Array.

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

Wenn Sie Dateien für Angular App \ Resources \ Direktiven und andere Dinge getrennt haben, können Sie die Minimierung Ihres Angular App-Bundles wie folgt deaktivieren (verwenden Sie neues Bundle () anstelle von ScriptBundle () in Ihrer Bundle-Konfigurationsdatei):

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"));

Und eckige App würde im Bundle unverändert erscheinen.

Schnapz
quelle
Über Leistung, was ist besser? Bundle () oder ScriptBundle ()?
Thomas.Benz
@ Thomas.Benz Mit Bundle () wird nur die Minimierung Ihrer Skripte deaktiviert. Das Problem hierbei ist, dass ScriptBundle () beim Minimieren einiger Angular-Skripte Funktionsnamen verkürzt und andere verwandte Aufgaben ausführt. Und wenn Angular versucht, einige interne Abhängigkeitsinjektionen oder ähnliches durchzuführen, konnte es keine geeigneten Funktionen dafür finden, da ihre Namen auf benutzerdefinierte Weise geändert wurden (z. B. von 'SuperController' in 's' oder sonst). Es ist daher besser, eckige Skripte unverändert zu lassen oder zu versuchen, eine andere Bibliothek zur Minimierung anstelle der Standardbibliothek zu verwenden.
Schnapz
1

Wenn Sie Dateien für Angular App \ Resources \ Direktiven und andere Dinge getrennt haben, können Sie die Minimierung Ihres Angular App-Bundles wie folgt deaktivieren (verwenden Sie neues Bundle () anstelle von ScriptBundle () in Ihrer Bundle-Konfigurationsdatei):

nirmal kumar
quelle
0

Fügen Sie die Dienste $ http, $ scope in die Controller-Funktion ein. Manchmal treten diese Fehler auf, wenn sie fehlen.

Omkar Dixit
quelle
0

Ich hatte das gleiche Problem, aber das Problem war ein anderes. Ich habe versucht, einen Dienst zu erstellen und $ scope als Parameter an ihn zu übergeben.
Dies ist eine weitere Möglichkeit, diesen Fehler zu erhalten, da in der Dokumentation dieses Links Folgendes angegeben ist:

Der Versuch, ein Bereichsobjekt in etwas einzufügen, das kein Controller oder eine Direktive ist, z. B. ein Dienst, löst auch einen unbekannten Anbieter aus: $ scopeProvider <- $ scope error. Dies kann passieren, wenn man einen Controller fälschlicherweise als Dienst registriert, z.

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.
}]);
Eugenio Miró
quelle