2012-11-28 24 views
20

Trường hợp sử dụng rất đơn giản: Tôi có hai bộ điều khiển chia sẻ cùng một sự phụ thuộc MyService. Dịch vụ này đang giữ một số trạng thái, cho phép ngồi myVariable. Nếu tôi đặt nó từ ControllerOne, thì nó cũng sẽ được phát hiện bởi ControllerTwo.Yêu cầu AngularJs trả lại một cá thể mới thông qua Dependency Injection

Điều tôi muốn là cho mỗi bộ điều khiển có thể hiện riêng của nó là MyService, sao cho myVariable có thể được thay đổi bởi mỗi Bộ điều khiển mà không ảnh hưởng đến bộ điều khiển kia.

Nói cách khác - tôi muốn trường hợp mới được trả về bởi Dependency Injection, thay vì singleton.

+0

Xem thêm http://stackoverflow.com/a/13620494/215945 –

Trả lời

20

Không trực tiếp như bạn mong đợi. Các thể hiện dịch vụ được tạo ra lần đầu tiên chúng được lấy bởi bộ phun và được duy trì bởi bộ phun ... nói cách khác, chúng luôn luôn là các bộ đơn. The magic happens in here, đặc biệt nhìn vào hàm provider, trong đó đặt cá thể nhà cung cấp trong đối tượng providerCache.

Nhưng đừng mất hy vọng, bạn có thể cũng giống như dễ dàng thêm nhà xây dựng cho bất cứ điều gì bạn muốn chia sẻ trong một dịch vụ, nếu bạn để chọn:

app.factory('myService', [function() { 
    var i = 1; 

    function Foo() { 
     this.bar = "I'm Foo " + i++; 
    }; 

    return { 
      Foo: Foo 
    }; 
}]); 

app.controller('Ctrl1', function($scope, myService) { 
    $scope.foo = new myService.Foo(); 
    console.log($scope.foo.bar) //I'm Foo 1 
}); 

app.controller('Ctrl2', function($scope, myService) { 
    $scope.foo = new myService.Foo(); 
    console.log($scope.foo.bar) //I'm Foo 2 
}); 

EDIT: như OP chỉ ra, đó cũng là $injector.instantiate, mà bạn có thể sử dụng để gọi các nhà thầu JavaScript bên ngoài bộ điều khiển của mình. Tôi không chắc chắn những gì các tác động là của testability ở đây, nhưng nó cung cấp cho bạn một cách khác để tiêm mã sẽ xây dựng một đối tượng mới cho bạn.

+4

Ngoài ra còn có một cách khác. Bạn có thể chỉ cần tạo một đối tượng với các phụ thuộc cần thiết (Component X) và sau đó tiêm nó trực tiếp với '$ injector.instantiate (ComponentX, {})'. Đối số thứ hai có thể chứa tất cả các biến 'statefull'. Dễ dàng và thanh lịch, cảm ơn bạn Angular Js! Có lẽ bạn có thể thêm nó vào phản hồi của bạn như một giải pháp thay thế, xin vui lòng? –

+1

Dường như khó kiểm tra hơn. –

+0

Dường như là giải pháp, nhưng bạn chỉ cần trả về hàm tạo. Tất cả các phương thức khác mà bạn có thể trả lại sẽ không bao giờ ảnh hưởng đến bất kỳ trường hợp nào bạn sẽ tạo sau này, trừ khi bạn thêm chúng vào nguyên mẫu của hàm tạo của bạn ... Xem câu trả lời karlgold, gần như là hoàn hảo. –

3

Có rất nhiều các phương án chung cho modularizing mã JavaScript, nhưng nếu bạn muốn làm một cái gì đó mà chỉ dựa vào AngularJS, mô hình này hoạt động:

1) Trước tiên xác định các lớp mà bạn muốn tiêm nhiều lần:

function MyClass() { 
    // ... 
} 

MyClass.prototype.memberMethod = function() { 
    // ... 
} 

2) Tiếp theo, làm cho các nhà xây dựng sẵn như là một hằng số:

angular.module('myModule').constant('MyClass', MyClass); 

3) Cuối cùng, sử dụng các mô hình nhà máy để tạo ra các trường hợp được đặt tên, được tiêm của lớp học:

angular.module('myOtherModule', ['myModule']).factory('instanceOfMyClass', [ 
    'MyClass', 
    function(MyClass) { return new MyClass(); } 
]); 
+0

Ý tưởng hay. Nhưng điều này không làm việc nếu nguyên mẫu của bạn cần tiêm mà không thể được thực hiện với hằng số, không phải giá trị ... Trong trường hợp này, tôi đoán việc tạo ra một dịch vụ là một lựa chọn tốt hơn. –

Các vấn đề liên quan