"Errore non rilevato: [$ injector: unpr]" con angolare dopo la distribuzione


97

Ho un'applicazione Angular abbastanza semplice che funziona perfettamente sulla mia macchina di sviluppo, ma non riesce con questo messaggio di errore (nella console del browser) dopo averlo distribuito:

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

Nessun altro messaggio oltre a quello. Succede quando la pagina viene caricata per la prima volta.

Sto eseguendo ASP.NET MVC5, Angular 1.2RC3 e sto eseguendo il push in Azure tramite git.

Google non ha trovato nulla di interessante.

Eventuali suggerimenti?

MODIFICARE:

Sto usando TypeScript e definisco le mie dipendenze con la $injectvariabile, ad esempio:

export class DashboardCtrl {

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

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

Credo che dovrebbe (o è inteso a) aggirare i problemi di ridenominazione delle variabili locali che si verificano durante la minificazione e che possono causare questo errore.

Detto questo, ha chiaramente qualcosa a che fare con il processo di minimizzazione, poiché quando ho impostato la BundleTable.EnableOptimizations = truemia macchina di sviluppo, posso riprodurlo.

Risposte:


163

Se segui il tuo collegamento, ti dice che l'errore deriva dal fatto che $ injector non è in grado di risolvere le tue dipendenze. Questo è un problema comune con angular quando il javascript viene minimizzato / sminuito / qualunque cosa tu stia facendo per la produzione.

Il problema è quando si dispone, ad esempio, di un controller;

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

La minificazione cambia $scopee $qin variabili casuali che non dicono ad angular cosa iniettare. La soluzione è dichiarare le tue dipendenze in questo modo:

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

Questo dovrebbe risolvere il tuo problema.

Tanto per ripetere, tutto ciò che ho detto è al link che ti fornisce il messaggio di errore.


2
Grazie per il suggerimento di visitare effettivamente il collegamento: avevo pensato che fosse un artefatto interno, non qualcosa a mio vantaggio. A quanto pare, sto definendo tutte le mie dipendenze tramite la $injectvariabile pubblica, che credo sia equivalente al modo in cui suggerisci (vedi docs.angularjs.org/guide/di ). Aggiornerò la mia domanda.
Ken Smith

2
Detto questo, ha chiaramente qualcosa a che fare con il processo di minificazione, poiché quando forzo le minificazioni ASP.NET MVC sulla mia macchina di sviluppo ( BundleTable.EnableOptimizations = true;), posso riprodurre il problema. Continuando a guardare.
Ken Smith

OK, capito. C'era un altro posto in cui stavo facendo DI di cui mi ero dimenticato, e si stava incasinando nel processo di minificazione. Grazie, questa è stata la risposta giusta.
Ken Smith

C'è anche un pacchetto che lo gestirà automaticamente chiamato ngmin e una gemma corrispondente per Rails chiamata ngmin-rails .
bradleygriffith

2
@ RyanTuck - In altre parole, con codice non minimizzato, Angular può semplicemente guardare i nomi delle variabili nelle tue funzioni e fare una buona ipotesi su cosa deve essere iniettato. Ma con il codice minimizzato, i nomi delle variabili sono tutti mungiti, quindi ha bisogno di qualche altro meccanismo - un meccanismo che non cambia quando il codice viene minimizzato - per sapere cosa iniettare. È qui che entrano in gioco l'array $ inject e gli altri meccanismi.
Ken Smith

13

Mi sono imbattuto nello stesso problema io stesso, ma le mie definizioni del controller sembravano leggermente diverse da quelle sopra. Per i controller definiti in questo modo:

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

Basta aggiungere una riga dopo la dichiarazione che indica quali oggetti iniettare quando viene istanziato il controller:

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

Questo lo rende sicuro per la minificazione.


11

Questo problema si verifica quando il controller o la direttiva non sono specificati come una matrice di dipendenze e funzioni. Per esempio

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

Quando minificato Il '$ scope' passato alla funzione del controller è sostituito da un nome di variabile di una sola lettera. Ciò renderà angolare all'oscuro della dipendenza. Per evitare ciò, passare il nome della dipendenza insieme alla funzione come array.

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

10

Se hai file separati per app angolari \ risorse \ direttive e altre cose, puoi semplicemente disabilitare la minificazione del tuo bundle di app angolari in questo modo (usa new Bundle () invece di ScriptBundle () nel tuo file di configurazione del 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"));

E l'app angolare apparirà in bundle non modificata.


A proposito di prestazioni, quale è meglio? Bundle () o ScriptBundle ()?
Thomas.Benz

@ Thomas.Benz L'uso di Bundle () disabiliterà solo la minificazione per i tuoi script. Il problema qui è che quando ScriptBundle () minimizza alcuni script angolari, accorcia i nomi delle funzioni e fa altre cose correlate. E quando Angular cerca di eseguire alcune iniezioni di dipendenze interne, o qualcosa del genere, non riesce a trovare le funzioni appropriate per questo, perché i loro nomi sono stati modificati in modo personalizzato (come da "SuperController" a "s" o altro). Quindi è meglio lasciare gli script angolari non modificati o provare a utilizzare qualche altra libreria per la minimizzazione invece di quella predefinita.
Schnapz

1

Se hai file separati per app angolari \ risorse \ direttive e altre cose, puoi semplicemente disabilitare la minificazione del tuo bundle di app angolari in questo modo (usa new Bundle () invece di ScriptBundle () nel tuo file di configurazione del bundle):


0

Aggiungere i servizi $ http, $ scope nella funzione del controller, a volte se mancano si verificano questi errori.


0

Ho avuto lo stesso problema ma il problema era diverso, stavo cercando di creare un servizio e passarvi $ scope come parametro.
Questo è un altro modo per ottenere questo errore come dice la documentazione di quel collegamento:

Il tentativo di inserire un oggetto di ambito in qualsiasi cosa che non sia un controller o una direttiva, ad esempio un servizio, genererà anche un provider sconosciuto: $ scopeProvider <- $ scope error. Ciò potrebbe accadere se si registra erroneamente un controller come servizio, ad esempio:

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.
}]);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.