“Kesalahan Tidak Tertangkap: [$ injektor: tidak]” dengan sudut setelah penerapan

97

Saya memiliki aplikasi Angular yang cukup sederhana yang berjalan dengan baik di mesin dev saya, tetapi gagal dengan pesan kesalahan ini (di konsol browser) setelah saya menerapkannya:

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

Tidak ada pesan lain selain itu. Itu terjadi saat halaman pertama kali dimuat.

Saya menjalankan ASP.NET MVC5, Angular 1.2RC3, dan mendorong ke Azure melalui git.

Googling belum menghasilkan sesuatu yang menarik.

Ada saran?

EDIT:

Saya menggunakan TypeScript, dan mendefinisikan dependensi saya dengan $injectvariabel, misalnya:

export class DashboardCtrl {

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

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

Saya percaya bahwa harus (atau dimaksudkan untuk) mengatasi masalah penggantian nama variabel lokal yang muncul selama minifikasi dan yang dapat menyebabkan kesalahan ini.

Meski begitu, ini jelas ada hubungannya dengan proses minifikasi, seperti saat saya menyetel BundleTable.EnableOptimizations = truemesin dev, saya bisa mereproduksinya.

Ken Smith
sumber

Jawaban:

163

Jika Anda mengikuti tautan Anda, ini memberi tahu Anda bahwa hasil kesalahan dari $ injektor tidak dapat menyelesaikan ketergantungan Anda. Ini adalah masalah umum dengan angular ketika javascript dikecilkan / di-uglified / apa pun yang Anda lakukan untuk produksi.

Masalahnya adalah ketika Anda memiliki misalnya pengontrol;

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

Minifikasi berubah $scopedan $qmenjadi variabel acak yang tidak memberi tahu sudut apa yang harus dimasukkan. Solusinya adalah mendeklarasikan dependensi Anda seperti ini:

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

Itu seharusnya memperbaiki masalah Anda.

Hanya untuk mengulang, semua yang saya katakan ada di tautan yang diberikan pesan kesalahan kepada Anda.

Stuart Nelson
sumber
2
Terima kasih atas saran untuk benar-benar mengunjungi tautan - Saya berasumsi itu adalah artefak internal, bukan sesuatu untuk keuntungan saya. Ternyata, saya mendefinisikan semua dependensi saya melalui $injectvariabel publik, yang menurut saya setara dengan cara yang Anda sarankan (lihat docs.angularjs.org/guide/di ). Saya akan memperbarui pertanyaan saya.
Ken Smith
2
Yang mengatakan, itu jelas ada hubungannya dengan proses minifikasi, seperti ketika saya memaksa minifikasi ASP.NET MVC pada mesin dev saya ( BundleTable.EnableOptimizations = true;), saya dapat mereproduksi masalah. Melanjutkan untuk melihat.
Ken Smith
Oke, aku sudah tahu. Ada tempat lain yang saya lakukan DI yang saya lupakan, dan itu semakin kacau dalam proses minifikasi. Terima kasih, ini jawaban yang benar.
Ken Smith
Ada juga paket yang secara otomatis akan menangani ini untuk Anda yang disebut ngmin dan permata yang sesuai untuk Rails disebut ngmin-rails .
bradleygriffith
2
@RyanTuck - Dengan kata lain, dengan kode yang tidak diminimalkan, Angular hanya dapat melihat nama variabel di fungsi Anda, dan menebak dengan baik tentang apa yang perlu disuntikkan. Tetapi dengan kode yang diperkecil, nama variabel semuanya diperkecil, jadi dibutuhkan beberapa mekanisme lain - mekanisme yang tidak berubah ketika kode dikecilkan - untuk mengetahui apa yang harus disuntikkan. Di situlah array $ inject dan mekanisme lainnya ikut bermain.
Ken Smith
13

Saya sendiri mengalami masalah yang sama, tetapi definisi pengontrol saya terlihat sedikit berbeda dari di atas. Untuk pengontrol yang ditentukan seperti ini:

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

Cukup tambahkan baris setelah deklarasi yang menunjukkan objek mana yang akan dimasukkan saat pengontrol dibuat:

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

Ini membuatnya aman untuk minifikasi.

Matt
sumber
11

Masalah ini terjadi ketika pengontrol atau direktif tidak ditentukan sebagai larik dependensi dan fungsi. Sebagai contoh

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

Ketika diminimalkan, '$ scope' yang diteruskan ke fungsi controller diganti dengan nama variabel satu huruf. Ini akan membuat sudut tidak mengerti ketergantungan. Untuk menghindari hal ini, berikan nama dependensi bersama dengan fungsi sebagai array.

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

Jika Anda telah memisahkan file untuk aplikasi sudut \ resources \ directives dan hal-hal lain, maka Anda dapat menonaktifkan minifikasi bundel aplikasi sudut Anda seperti ini (gunakan Bundle baru () alih-alih ScriptBundle () di file konfigurasi bundel Anda):

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

Dan aplikasi sudut akan muncul dalam bundel yang tidak dimodifikasi.

Schnapz
sumber
Soal performa, mana yang lebih baik? Bundle () atau ScriptBundle ()?
Thomas.Benz
@ Thomas.Benz Penggunaan Bundle () hanya akan menonaktifkan minifikasi untuk skrip Anda. Masalah di sini adalah ketika ScriptBundle () mengecilkan beberapa skrip Angular, itu mempersingkat nama fungsi dan melakukan hal-hal terkait lainnya. Dan ketika Angular mencoba melakukan beberapa injeksi ketergantungan internal, atau sesuatu seperti itu, ia tidak dapat menemukan fungsi yang tepat untuk itu, karena nama mereka diubah dengan cara khusus (seperti dari 'SuperController' menjadi 's' atau lainnya). Jadi lebih baik membiarkan skrip sudut tidak dimodifikasi atau mencoba menggunakan beberapa perpustakaan lain untuk minifikasi daripada yang default.
Schnapz
1

Jika Anda telah memisahkan file untuk aplikasi sudut \ resources \ directives dan hal-hal lain, maka Anda dapat menonaktifkan minifikasi bundel aplikasi sudut Anda seperti ini (gunakan Bundle baru () alih-alih ScriptBundle () di file konfigurasi bundel Anda):

nirmal kumar
sumber
0

Tambahkan $ http, $ scope services di controller fucntion, terkadang jika mereka tidak ada kesalahan ini terjadi.

Omkar Dixit
sumber
0

Saya memiliki masalah yang sama tetapi masalahnya berbeda, saya mencoba membuat layanan dan mengirimkan $ scope ke sana sebagai parameter.
Itu cara lain untuk mendapatkan kesalahan ini seperti dokumentasi tautan itu:

Mencoba memasukkan objek cakupan ke dalam apa pun yang bukan pengontrol atau arahan, misalnya layanan, juga akan memunculkan penyedia Tidak Dikenal: $ scopeProvider <- $ scope error. Ini mungkin terjadi jika seseorang salah mendaftarkan pengontrol sebagai layanan, mis .:

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ó
sumber