“Lỗi chưa xảy ra: [$ injectionor: unr]” với góc sau khi triển khai


97

Tôi có một ứng dụng Angular khá đơn giản chạy tốt trên máy dev của mình, nhưng không thành công với thông báo lỗi này (trong bảng điều khiển trình duyệt) sau khi tôi triển khai nó:

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

Không có tin nhắn nào khác ngoài điều đó. Nó xảy ra khi trang tải lần đầu tiên.

Tôi đang chạy ASP.NET MVC5, Angular 1.2RC3 và đẩy sang Azure qua git.

Googling không đưa ra bất kỳ điều gì thú vị.

Bất kỳ đề xuất?

BIÊN TẬP:

Tôi đang sử dụng TypeScript và xác định các phụ thuộc của tôi với $injectbiến, ví dụ:

export class DashboardCtrl {

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

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

Tôi tin rằng điều đó nên (hoặc dự định) giải quyết các vấn đề đổi tên biến cục bộ phát sinh trong quá trình rút gọn và có thể gây ra lỗi này.

Điều đó nói rằng, nó rõ ràng có liên quan đến quá trình thu nhỏ, như khi tôi thiết lập BundleTable.EnableOptimizations = truetrên máy dev của mình, tôi có thể tái tạo nó.

Câu trả lời:


163

Nếu bạn nhấp vào liên kết của mình, nó sẽ cho bạn biết rằng lỗi do $ injectionor không thể giải quyết các phần phụ thuộc của bạn. Đây là một vấn đề phổ biến với angle khi javascript được rút gọn / chưa được xác minh / bất cứ điều gì bạn đang làm với nó để sản xuất.

Vấn đề là khi bạn có ví dụ như một bộ điều khiển;

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

Sự thu nhỏ thay đổi $scope$qthành các biến ngẫu nhiên không cho biết những gì cần tiêm. Giải pháp là khai báo các phụ thuộc của bạn như sau:

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

Điều đó sẽ khắc phục vấn đề của bạn.

Chỉ cần lặp lại, mọi thứ tôi đã nói đều nằm ở liên kết mà thông báo lỗi cung cấp cho bạn.


2
Cảm ơn vì đề xuất thực sự truy cập vào liên kết - tôi đã cho rằng đó là một số tạo tác nội bộ, không phải thứ gì đó vì lợi ích của tôi. Hóa ra, tôi đang xác định tất cả các phụ thuộc của mình thông qua $injectbiến công khai, mà tôi tin rằng tương đương với cách bạn đề xuất (xem docs.angularjs.org/guide/di ). Tôi sẽ cập nhật câu hỏi của tôi.
Ken Smith

2
Điều đó nói rằng, nó rõ ràng có liên quan đến quá trình thu nhỏ, vì khi tôi ép buộc thu nhỏ ASP.NET MVC trên máy dev của mình ( BundleTable.EnableOptimizations = true;), tôi có thể tái tạo vấn đề. Tiếp tục nhìn.
Ken Smith

OK, đã tìm ra. Có một nơi khác mà tôi đang thực hiện DI mà tôi đã quên mất, và nó đang bị rối tung trong quá trình thu nhỏ. Cảm ơn, đây là câu trả lời đúng.
Ken Smith,

Ngoài ra còn có một gói sẽ tự động xử lý điều này cho bạn được gọi là ngmin và một viên ngọc tương ứng cho Rails được gọi là ngmin-rails .
bradleygriffith

2
@RyanTuck - Nói cách khác, với mã chưa được hợp nhất, Angular có thể chỉ cần xem các tên biến trong các hàm của bạn và đưa ra phỏng đoán chính xác về những gì cần được đưa vào. Nhưng với mã được rút gọn, các tên biến đều được trộn lẫn, vì vậy nó cần một số cơ chế khác - một cơ chế không thay đổi khi mã được rút gọn - để biết những gì cần đưa vào. Đó là nơi mà mảng $ injection và các cơ chế khác phát huy tác dụng.
Ken Smith

13

Bản thân tôi cũng gặp phải vấn đề tương tự, nhưng định nghĩa bộ điều khiển của tôi trông hơi khác so với ở trên. Đối với bộ điều khiển được định nghĩa như thế này:

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

Chỉ cần thêm một dòng sau phần khai báo cho biết đối tượng nào sẽ được đưa vào khi bộ điều khiển được khởi tạo:

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

Điều này làm cho nó an toàn.


11

Sự cố này xảy ra khi bộ điều khiển hoặc chỉ thị không được chỉ định là một mảng phụ thuộc và chức năng. Ví dụ

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

Khi được rút gọn, '$ scope' được truyền cho hàm controller được thay thế bằng một tên biến ký tự đơn. Điều này sẽ làm cho sự phụ thuộc trở nên vô nghĩa. Để tránh điều này, hãy chuyển tên phụ thuộc cùng với hàm dưới dạng một mảng.

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

10

Nếu bạn đã tách các tệp cho ứng dụng góc cạnh \ resources \ chỉ thị và các nội dung khác thì bạn chỉ có thể tắt tính năng thu nhỏ gói ứng dụng góc cạnh của mình như thế này (sử dụng Gói ứng dụng mới () thay vì ScriptBundle () trong tệp cấu hình gói của bạn):

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

Và ứng dụng góc cạnh sẽ xuất hiện trong gói không được sửa đổi.


Về hiệu suất, cái nào tốt hơn? Bundle () hay ScriptBundle ()?
Thomas.Benz

@ Thomas.Benz Việc sử dụng Bundle () sẽ chỉ tắt tính năng thu nhỏ cho các tập lệnh của bạn. Vấn đề ở đây là khi ScriptBundle () thu nhỏ một số tập lệnh Angular, nó sẽ rút ngắn tên hàm và thực hiện những thứ liên quan khác. Và khi Angular cố gắng thực hiện một số lần tiêm phụ thuộc nội bộ, hoặc tương tự như vậy, nó không thể tìm thấy các chức năng thích hợp cho việc đó, vì tên của chúng đã được thay đổi theo cách tùy chỉnh (như từ 'SuperController' thành 's' hoặc khác). Vì vậy, tốt hơn là để các tập lệnh góc cạnh không được sửa đổi hoặc cố gắng sử dụng một số thư viện khác để thu nhỏ thay vì thư viện mặc định.
Schnapz

1

Nếu bạn đã tách các tệp cho ứng dụng góc cạnh \ resources \ chỉ thị và các nội dung khác thì bạn chỉ có thể tắt tính năng thu nhỏ gói ứng dụng góc cạnh của mình như thế này (sử dụng Gói ứng dụng mới () thay vì ScriptBundle () trong tệp cấu hình gói của bạn):


0

Thêm các dịch vụ $ http, $ scope trong controller fucntion, đôi khi nếu chúng bị thiếu, những lỗi này sẽ xảy ra.


0

Tôi đã gặp vấn đề tương tự nhưng vấn đề là một vấn đề khác, tôi đang cố gắng tạo một dịch vụ và chuyển $ scope cho nó dưới dạng tham số.
Đó là một cách khác để gặp lỗi này như tài liệu của liên kết đó cho biết:

Cố gắng đưa một đối tượng phạm vi vào bất kỳ thứ gì không phải là bộ điều khiển hoặc chỉ thị, ví dụ như một dịch vụ, cũng sẽ gây ra lỗi Nhà cung cấp không xác định: $ scopeProvider <- $ scope. Điều này có thể xảy ra nếu một người đăng ký nhầm bộ điều khiển như một dịch vụ, ví dụ:

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.
}]);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.