Sự khác nhau giữa là gì Service
, Provider
và Factory
tại AngularJS?
service.factory
. Không muốn làm phức tạp thêm chủ đề này.
Sự khác nhau giữa là gì Service
, Provider
và Factory
tại AngularJS?
service.factory
. Không muốn làm phức tạp thêm chủ đề này.
Câu trả lời:
Từ danh sách gửi thư của AngularJS, tôi đã nhận được một chủ đề tuyệt vời giải thích dịch vụ so với nhà máy và nhà cung cấp và việc sử dụng thuốc tiêm của họ. Tổng hợp các câu trả lời:
Cú pháp: module.service( 'serviceName', function );
Kết quả: Khi khai báo serviceName dưới dạng đối số có thể tiêm, bạn sẽ được cung cấp một thể hiện của hàm. Nói cách khácnew FunctionYouPassedToService()
.
Cú pháp: module.factory( 'factoryName', function );
Kết quả: Khi khai báo FactoryName là đối số có thể tiêm, bạn sẽ được cung cấp giá trị được trả về bằng cách gọi tham chiếu hàm được truyền cho module.factory .
Cú pháp: module.provider( 'providerName', function );
Kết quả: Khi khai báo CarrierName là đối số có thể tiêm, bạn sẽ được cung cấp(new ProviderFunction()).$get()
. Hàm constructor được khởi tạo trước khi phương thức $ get được gọi - ProviderFunction
là tham chiếu hàm được truyền cho module.provider.
Các nhà cung cấp có lợi thế là họ có thể được cấu hình trong giai đoạn cấu hình mô-đun.
Xem ở đây để biết mã được cung cấp.
Đây là một lời giải thích tuyệt vời hơn nữa của Misko:
provide.value('a', 123);
function Controller(a) {
expect(a).toEqual(123);
}
Trong trường hợp này, người tiêm chỉ cần trả về giá trị như hiện tại. Nhưng nếu bạn muốn tính giá trị thì sao? Sau đó sử dụng một nhà máy
provide.factory('b', function(a) {
return a*2;
});
function Controller(b) {
expect(b).toEqual(246);
}
Vì vậy, factory
là một chức năng chịu trách nhiệm tạo ra giá trị. Lưu ý rằng chức năng của nhà máy có thể yêu cầu các phụ thuộc khác.
Nhưng nếu bạn muốn trở thành OO nhiều hơn và có một lớp gọi là Greeter thì sao?
function Greeter(a) {
this.greet = function() {
return 'Hello ' + a;
}
}
Sau đó, để khởi tạo bạn sẽ phải viết
provide.factory('greeter', function(a) {
return new Greeter(a);
});
Sau đó, chúng ta có thể yêu cầu 'người chào' trong bộ điều khiển như thế này
function Controller(greeter) {
expect(greeter instanceof Greeter).toBe(true);
expect(greeter.greet()).toEqual('Hello 123');
}
Nhưng đó là cách quá dài dòng. Một cách ngắn hơn để viết này sẽ làprovider.service('greeter', Greeter);
Nhưng nếu chúng ta muốn cấu hình Greeter
lớp trước khi tiêm thì sao? Sau đó chúng ta có thể viết
provide.provider('greeter2', function() {
var salutation = 'Hello';
this.setSalutation = function(s) {
salutation = s;
}
function Greeter(a) {
this.greet = function() {
return salutation + ' ' + a;
}
}
this.$get = function(a) {
return new Greeter(a);
};
});
Sau đó chúng ta có thể làm điều này:
angular.module('abc', []).config(function(greeter2Provider) {
greeter2Provider.setSalutation('Halo');
});
function Controller(greeter2) {
expect(greeter2.greet()).toEqual('Halo 123');
}
Là một mặt lưu ý, service
, factory
, và value
tất cả đều có nguồn gốc từ nhà cung cấp.
provider.service = function(name, Class) {
provider.provide(name, function() {
this.$get = function($injector) {
return $injector.instantiate(Class);
};
});
}
provider.factory = function(name, factory) {
provider.provide(name, function() {
this.$get = function($injector) {
return $injector.invoke(factory);
};
});
}
provider.value = function(name, value) {
provider.factory(name, function() {
return value;
});
};
toEqual
và greeter.Greet
là gì. Tại sao không sử dụng một cái gì đó hơi thực tế và dễ hiểu hơn?
factory
/ service
/ provider
:var myApp = angular.module('myApp', []);
//service style, probably the simplest one
myApp.service('helloWorldFromService', function() {
this.sayHello = function() {
return "Hello, World!";
};
});
//factory style, more involved but more sophisticated
myApp.factory('helloWorldFromFactory', function() {
return {
sayHello: function() {
return "Hello, World!";
}
};
});
//provider style, full blown, configurable version
myApp.provider('helloWorld', function() {
this.name = 'Default';
this.$get = function() {
var name = this.name;
return {
sayHello: function() {
return "Hello, " + name + "!";
}
}
};
this.setName = function(name) {
this.name = name;
};
});
//hey, we can configure a provider!
myApp.config(function(helloWorldProvider){
helloWorldProvider.setName('World');
});
function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) {
$scope.hellos = [
helloWorld.sayHello(),
helloWorldFromFactory.sayHello(),
helloWorldFromService.sayHello()];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="MyCtrl">
{{hellos}}
</div>
</body>
this
thay đổi bối cảnh trong $get
chức năng? - bạn không còn đề cập đến nhà cung cấp khởi tạo trong chức năng đó.
this
thực tế không thay đổi ngữ cảnh, bởi vì cái được gọi là new Provider()
. $ Get (), Provider
hàm được truyền đến đâu app.provider
. Điều đó có nghĩa $get()
là đang được gọi là một phương thức trên được xây dựng Provider
, vì vậy this
sẽ đề cập đến Provider
như ví dụ gợi ý.
Unknown provider: helloWorldProvider <- helloWorld
khi chạy này cục bộ? Nhận xét nó, lỗi tương tự cho 2 ví dụ khác. Có một số cấu hình nhà cung cấp ẩn? (Angular 1.0.8) - Đã tìm thấy: stackoverflow.com/questions/12339272/iêu
TL; DR
1) Khi bạn đang sử dụng Factory, bạn tạo một đối tượng, thêm thuộc tính cho nó, sau đó trả về cùng một đối tượng đó. Khi bạn chuyển nhà máy này vào bộ điều khiển của mình, các thuộc tính đó trên đối tượng sẽ có sẵn trong bộ điều khiển đó thông qua nhà máy của bạn.
app.controller(‘myFactoryCtrl’, function($scope, myFactory){
$scope.artist = myFactory.getArtist();
});
app.factory(‘myFactory’, function(){
var _artist = ‘Shakira’;
var service = {};
service.getArtist = function(){
return _artist;
}
return service;
});
2) Khi bạn đang sử dụng Dịch vụ , AngularJS sẽ khởi tạo nó phía sau hậu trường với từ khóa 'mới'. Do đó, bạn sẽ thêm thuộc tính vào 'cái này' và dịch vụ sẽ trả về 'cái này'. Khi bạn chuyển dịch vụ vào bộ điều khiển của mình, các thuộc tính đó trên 'this' sẽ có sẵn trên bộ điều khiển đó thông qua dịch vụ của bạn.
app.controller(‘myServiceCtrl’, function($scope, myService){
$scope.artist = myService.getArtist();
});
app.service(‘myService’, function(){
var _artist = ‘Nelly’;
this.getArtist = function(){
return _artist;
}
});
3) Nhà cung cấp là dịch vụ duy nhất bạn có thể chuyển vào hàm .config (). Sử dụng nhà cung cấp khi bạn muốn cung cấp cấu hình toàn mô-đun cho đối tượng dịch vụ của mình trước khi cung cấp.
app.controller(‘myProvider’, function($scope, myProvider){
$scope.artist = myProvider.getArtist();
$scope.data.thingFromConfig = myProvider.thingOnConfig;
});
app.provider(‘myProvider’, function(){
//Only the next two lines are available in the app.config()
this._artist = ‘’;
this.thingFromConfig = ‘’;
this.$get = function(){
var that = this;
return {
getArtist: function(){
return that._artist;
},
thingOnConfig: that.thingFromConfig
}
}
});
app.config(function(myProviderProvider){
myProviderProvider.thingFromConfig = ‘This was set in config’;
});
Không TL; DR
1) Nhà máy của
nhà máy là cách phổ biến nhất để tạo và định cấu hình dịch vụ. Thực sự không có nhiều hơn những gì TL; DR nói. Bạn chỉ cần tạo một đối tượng, thêm thuộc tính cho nó, sau đó trả lại cùng một đối tượng đó. Sau đó, khi bạn chuyển nhà máy vào bộ điều khiển của mình, các thuộc tính đó trên đối tượng sẽ có sẵn trong bộ điều khiển đó thông qua nhà máy của bạn. Một ví dụ rộng hơn là dưới đây.
app.factory(‘myFactory’, function(){
var service = {};
return service;
});
Bây giờ, bất kỳ thuộc tính nào chúng tôi đính kèm vào 'dịch vụ' sẽ có sẵn cho chúng tôi khi chúng tôi chuyển 'myFactory' vào bộ điều khiển của chúng tôi.
Bây giờ, hãy thêm một số biến 'riêng tư' vào chức năng gọi lại của chúng tôi. Chúng không thể truy cập trực tiếp từ bộ điều khiển, nhưng cuối cùng chúng tôi sẽ thiết lập một số phương thức getter / setter trên 'dịch vụ' để có thể thay đổi các biến 'riêng tư' này khi cần.
app.factory(‘myFactory’, function($http, $q){
var service = {};
var baseUrl = ‘https://itunes.apple.com/search?term=’;
var _artist = ‘’;
var _finalUrl = ‘’;
var makeUrl = function(){
_artist = _artist.split(‘ ‘).join(‘+’);
_finalUrl = baseUrl + _artist + ‘&callback=JSON_CALLBACK’;
return _finalUrl
}
return service;
});
Ở đây bạn sẽ nhận thấy chúng tôi không gắn các biến / chức năng đó vào 'dịch vụ'. Chúng tôi chỉ đơn giản là tạo chúng để sử dụng hoặc sửa đổi chúng sau này.
Bây giờ, các biến và hàm trợ giúp / riêng tư của chúng ta đã sẵn sàng, hãy thêm một số thuộc tính vào đối tượng 'dịch vụ'. Bất cứ điều gì chúng tôi đưa vào 'dịch vụ' đều có thể được sử dụng trực tiếp bên trong bất kỳ bộ điều khiển nào chúng tôi chuyển 'myFactory' vào.
Chúng ta sẽ tạo các phương thức setArtist và getArtist chỉ đơn giản là trả về hoặc đặt nghệ sĩ. Chúng tôi cũng sẽ tạo một phương thức sẽ gọi API iTunes bằng URL được tạo của chúng tôi. Phương pháp này sẽ trả lại một lời hứa sẽ thực hiện khi dữ liệu đã quay trở lại từ API iTunes. Nếu bạn chưa có nhiều kinh nghiệm sử dụng lời hứa trong AngularJS, tôi khuyên bạn nên thực hiện một cuộc lặn sâu vào chúng.
Dưới đây setArtist chấp nhận một nghệ sĩ và cho phép bạn đặt nghệ sĩ. getArtist trả lại nghệ sĩ. callItunes trước tiên gọi makeUrl () để tạo URL chúng tôi sẽ sử dụng với yêu cầu $ http của chúng tôi. Sau đó, nó thiết lập một đối tượng lời hứa, thực hiện một yêu cầu $ http với url cuối cùng của chúng tôi, sau đó vì $ http trả lại một lời hứa, chúng tôi có thể gọi .success hoặc .error sau yêu cầu của chúng tôi. Sau đó, chúng tôi giải quyết lời hứa của chúng tôi với dữ liệu iTunes hoặc chúng tôi từ chối nó với thông báo 'Có lỗi'.
app.factory('myFactory', function($http, $q){
var service = {};
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
service.setArtist = function(artist){
_artist = artist;
}
service.getArtist = function(){
return _artist;
}
service.callItunes = function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
}
return service;
});
Bây giờ nhà máy của chúng tôi đã hoàn thành. Bây giờ chúng tôi có thể đưa 'myFactory' vào bất kỳ bộ điều khiển nào và sau đó chúng tôi sẽ có thể gọi các phương thức mà chúng tôi đã gắn vào đối tượng dịch vụ của mình (setArtist, getArtist và callItunes).
app.controller('myFactoryCtrl', function($scope, myFactory){
$scope.data = {};
$scope.updateArtist = function(){
myFactory.setArtist($scope.data.artist);
};
$scope.submitArtist = function(){
myFactory.callItunes()
.then(function(data){
$scope.data.artistData = data;
}, function(data){
alert(data);
})
}
});
Trong bộ điều khiển ở trên, chúng tôi đang tiêm dịch vụ 'myFactory'. Sau đó, chúng tôi đặt thuộc tính trên đối tượng $ scope với dữ liệu từ 'myFactory'. Mã khó khăn duy nhất ở trên là nếu bạn chưa bao giờ thực hiện lời hứa trước đó. Vì callItunes đang trả lại một lời hứa, chúng tôi có thể sử dụng phương thức .then () và chỉ đặt $ scope.data.artistData sau khi lời hứa của chúng tôi được thực hiện với dữ liệu iTunes. Bạn sẽ nhận thấy bộ điều khiển của chúng tôi rất "mỏng" (Đây là một cách thực hành mã hóa tốt). Tất cả dữ liệu logic và liên tục của chúng tôi được đặt trong dịch vụ của chúng tôi, không phải trong bộ điều khiển của chúng tôi.
2) Dịch vụ
Có lẽ điều lớn nhất cần biết khi xử lý việc tạo Dịch vụ là nó được khởi tạo với từ khóa 'mới'. Đối với bạn các chuyên gia JavaScript, điều này sẽ cung cấp cho bạn một gợi ý lớn về bản chất của mã. Đối với những người bạn có nền tảng hạn chế về JavaScript hoặc cho những người không quá quen thuộc với từ khóa 'mới' thực sự làm gì, hãy xem xét một số nguyên tắc cơ bản về JavaScript cuối cùng sẽ giúp chúng tôi hiểu bản chất của Dịch vụ.
Để thực sự thấy những thay đổi xảy ra khi bạn gọi một hàm với từ khóa 'mới', hãy tạo một hàm và gọi nó bằng từ khóa 'mới', sau đó hãy cho biết trình thông dịch làm gì khi thấy từ khóa 'mới'. Kết quả cuối cùng sẽ giống nhau.
Trước tiên hãy tạo Trình xây dựng của chúng tôi.
var Person = function(name, age){
this.name = name;
this.age = age;
}
Đây là một hàm xây dựng JavaScript điển hình. Bây giờ, bất cứ khi nào chúng ta gọi hàm Person bằng từ khóa 'mới', 'this' sẽ bị ràng buộc với đối tượng mới được tạo.
Bây giờ, hãy thêm một phương thức vào nguyên mẫu của Người của chúng tôi để nó sẽ có sẵn trên mọi phiên bản của 'Người' của chúng tôi.
Person.prototype.sayName = function(){
alert(‘My name is ‘ + this.name);
}
Bây giờ, vì chúng tôi đặt hàm sayName trên nguyên mẫu, mọi phiên bản của Person sẽ có thể gọi hàm sayName để cảnh báo tên của cá thể đó.
Bây giờ chúng ta có hàm xây dựng Person và hàm sayName trên nguyên mẫu của nó, hãy thực sự tạo một thể hiện của Person sau đó gọi hàm sayName.
var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’
Vì vậy, tất cả các mã cùng nhau để tạo một hàm tạo Person, thêm một hàm vào nguyên mẫu của nó, tạo một cá thể Person, và sau đó gọi hàm trên nguyên mẫu của nó trông như thế này.
var Person = function(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayName = function(){
alert(‘My name is ‘ + this.name);
}
var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’
Bây giờ hãy xem điều gì đang thực sự xảy ra khi bạn sử dụng từ khóa 'mới' trong JavaScript. Điều đầu tiên bạn cần lưu ý là sau khi sử dụng 'new' trong ví dụ của chúng tôi, chúng tôi có thể gọi một phương thức (sayName) trên 'tyler' giống như đó là một đối tượng - đó là vì nó là. Vì vậy, trước tiên, chúng ta biết rằng hàm tạo Person của chúng ta đang trả về một đối tượng, cho dù chúng ta có thể thấy điều đó trong mã hay không. Thứ hai, chúng ta biết rằng vì hàm sayName của chúng ta nằm trên nguyên mẫu và không trực tiếp trên cá thể Person, nên đối tượng mà hàm Person đang trả về phải được ủy quyền cho nguyên mẫu của nó khi tra cứu thất bại. Nói một cách đơn giản hơn, khi chúng ta gọi tyler.sayName () trình thông dịch nói rằng OK OK, tôi sẽ xem xét đối tượng 'tyler' mà chúng ta vừa tạo, định vị hàm sayName, sau đó gọi nó. Đợi một chút, tôi không thấy nó ở đây - tất cả những gì tôi thấy là tên và tuổi, Hãy để tôi kiểm tra nguyên mẫu. Yup, có vẻ như nó trên nguyên mẫu, hãy để tôi gọi nó.
Dưới đây là mã cho cách bạn có thể nghĩ về những gì từ khóa 'mới' thực sự đang làm trong JavaScript. Về cơ bản, đây là một ví dụ mã của đoạn văn trên. Tôi đã đặt 'chế độ xem trình thông dịch' hoặc cách trình thông dịch nhìn thấy mã bên trong các ghi chú.
var Person = function(name, age){
//The below line creates an object(obj) that will delegate to the person’s prototype on failed lookups.
//var obj = Object.create(Person.prototype);
//The line directly below this sets ‘this’ to the newly created object
//this = obj;
this.name = name;
this.age = age;
//return this;
}
Bây giờ có kiến thức về những gì từ khóa 'mới' thực sự làm trong JavaScript, việc tạo một Dịch vụ trong AngularJS sẽ dễ hiểu hơn.
Điều lớn nhất cần hiểu khi tạo Dịch vụ là biết rằng Dịch vụ được khởi tạo với từ khóa 'mới'. Kết hợp kiến thức đó với các ví dụ của chúng tôi ở trên, giờ đây bạn sẽ nhận ra rằng bạn sẽ trực tiếp đính kèm các thuộc tính và phương thức của mình vào 'cái này' mà sau đó sẽ được trả về từ chính Dịch vụ. Chúng ta hãy xem điều này trong hành động.
Không giống như những gì chúng ta đã làm với ví dụ Factory, chúng ta không cần tạo một đối tượng sau đó trả về đối tượng đó bởi vì, như đã đề cập nhiều lần trước đó, chúng ta đã sử dụng từ khóa 'mới' để trình thông dịch sẽ tạo đối tượng đó, ủy thác cho nó đó là nguyên mẫu, sau đó trả lại cho chúng tôi mà không cần chúng tôi phải thực hiện công việc.
Trước tiên, hãy tạo chức năng 'riêng tư' và trợ giúp của chúng tôi. Điều này sẽ trông rất quen thuộc vì chúng tôi đã làm điều tương tự chính xác với nhà máy của chúng tôi. Tôi sẽ không giải thích mỗi dòng làm gì ở đây vì tôi đã làm điều đó trong ví dụ về nhà máy, nếu bạn bối rối, hãy đọc lại ví dụ về nhà máy.
app.service('myService', function($http, $q){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
});
Bây giờ, chúng tôi sẽ đính kèm tất cả các phương thức sẽ có trong bộ điều khiển của chúng tôi vào 'cái này'.
app.service('myService', function($http, $q){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
this.setArtist = function(artist){
_artist = artist;
}
this.getArtist = function(){
return _artist;
}
this.callItunes = function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
}
});
Bây giờ giống như trong nhà máy của chúng tôi, setArtist, getArtist và callItunes sẽ có sẵn trong bất kỳ bộ điều khiển nào chúng tôi chuyển myService vào. Đây là bộ điều khiển myService (gần giống hệt như bộ điều khiển nhà máy của chúng tôi).
app.controller('myServiceCtrl', function($scope, myService){
$scope.data = {};
$scope.updateArtist = function(){
myService.setArtist($scope.data.artist);
};
$scope.submitArtist = function(){
myService.callItunes()
.then(function(data){
$scope.data.artistData = data;
}, function(data){
alert(data);
})
}
});
Giống như tôi đã đề cập trước đây, một khi bạn thực sự hiểu những gì 'mới', Dịch vụ gần như giống hệt với các nhà máy ở AngularJS.
3) Nhà cung cấp
Điều lớn nhất cần nhớ về Nhà cung cấp là họ là dịch vụ duy nhất mà bạn có thể chuyển vào phần app.config trong ứng dụng của mình. Điều này có tầm quan trọng rất lớn nếu bạn cần thay đổi một phần đối tượng dịch vụ của mình trước khi nó có sẵn ở mọi nơi khác trong ứng dụng của bạn. Mặc dù rất giống với Dịch vụ / Nhà máy, có một vài điểm khác biệt mà chúng ta sẽ thảo luận.
Đầu tiên, chúng tôi thiết lập Nhà cung cấp của mình theo cách tương tự như chúng tôi đã làm với Dịch vụ và Nhà máy của mình. Các biến dưới đây là chức năng 'riêng tư' và trợ giúp của chúng tôi.
app.provider('myProvider', function(){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
//Going to set this property on the config function below.
this.thingFromConfig = ‘’;
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
}
* Một lần nữa nếu bất kỳ phần nào của đoạn mã trên gây nhầm lẫn, hãy xem phần Factory nơi tôi giải thích tất cả những gì nó làm chi tiết hơn.
Bạn có thể nghĩ về Nhà cung cấp có ba phần. Phần đầu tiên là các biến / hàm 'riêng tư' sẽ được sửa đổi / thiết lập sau (hiển thị ở trên). Phần thứ hai là các biến / hàm sẽ có sẵn trong hàm app.config của bạn và do đó có sẵn để thay đổi trước khi chúng có sẵn ở bất kỳ nơi nào khác (cũng được hiển thị ở trên). Điều quan trọng cần lưu ý là các biến đó cần được gắn vào từ khóa 'this'. Trong ví dụ của chúng tôi, chỉ 'thingFromConfig' sẽ có sẵn để thay đổi trong app.config. Phần thứ ba (hiển thị bên dưới) là tất cả các biến / hàm sẽ có trong bộ điều khiển của bạn khi bạn chuyển dịch vụ 'myProvider' vào bộ điều khiển cụ thể đó.
Khi tạo một dịch vụ với Nhà cung cấp, các thuộc tính / phương thức duy nhất có sẵn trong bộ điều khiển của bạn là các thuộc tính / phương thức được trả về từ hàm $ get (). Đoạn mã dưới đây đặt $ get vào 'this' (mà chúng ta biết cuối cùng sẽ được trả về từ hàm đó). Bây giờ, hàm $ get trả về tất cả các phương thức / thuộc tính mà chúng ta muốn có sẵn trong bộ điều khiển. Đây là một ví dụ mã.
this.$get = function($http, $q){
return {
callItunes: function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
},
setArtist: function(artist){
_artist = artist;
},
getArtist: function(){
return _artist;
},
thingOnConfig: this.thingFromConfig
}
}
Bây giờ mã nhà cung cấp đầy đủ trông như thế này
app.provider('myProvider', function(){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
//Going to set this property on the config function below
this.thingFromConfig = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
this.$get = function($http, $q){
return {
callItunes: function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
},
setArtist: function(artist){
_artist = artist;
},
getArtist: function(){
return _artist;
},
thingOnConfig: this.thingFromConfig
}
}
});
Bây giờ giống như trong nhà máy và Dịch vụ của chúng tôi, setArtist, getArtist và callItunes sẽ có sẵn trong bất kỳ bộ điều khiển nào chúng tôi chuyển myProvider vào. Đây là bộ điều khiển myProvider (gần giống hệt như bộ điều khiển nhà máy / dịch vụ của chúng tôi).
app.controller('myProviderCtrl', function($scope, myProvider){
$scope.data = {};
$scope.updateArtist = function(){
myProvider.setArtist($scope.data.artist);
};
$scope.submitArtist = function(){
myProvider.callItunes()
.then(function(data){
$scope.data.artistData = data;
}, function(data){
alert(data);
})
}
$scope.data.thingFromConfig = myProvider.thingOnConfig;
});
Như đã đề cập trước đó, toàn bộ điểm tạo ra một dịch vụ với Nhà cung cấp là có thể thay đổi một số biến thông qua chức năng app.config trước khi đối tượng cuối cùng được chuyển đến phần còn lại của ứng dụng. Hãy xem một ví dụ về điều đó.
app.config(function(myProviderProvider){
//Providers are the only service you can pass into app.config
myProviderProvider.thingFromConfig = 'This sentence was set in app.config. Providers are the only service that can be passed into config. Check out the code to see how it works';
});
Bây giờ bạn có thể thấy 'thingFromConfig' là chuỗi rỗng trong nhà cung cấp của chúng tôi, nhưng khi nó xuất hiện trong DOM, nó sẽ là 'Câu này đã được đặt ra'.
Tất cả các dịch vụ là singletons ; họ được khởi tạo một lần cho mỗi ứng dụng. Chúng có thể thuộc bất kỳ loại nào , cho dù đó là kiểu nguyên thủy, nghĩa đen, hàm hoặc thậm chí là một thể hiện của loại tùy chỉnh.
Các value
, factory
, service
, constant
, và provider
các phương pháp đều là các nhà cung cấp. Họ dạy cho In phun cách khởi tạo Dịch vụ.
Cao nhất, nhưng cũng toàn diện nhất là một công thức Nhà cung cấp. Các Bốn còn lại loại recipe - Giá trị, Nhà máy, dịch vụ và Constant - chỉ là cú pháp đường trên đầu trang của một công thức cung cấp dịch vụ .
Bạn chỉ nên sử dụng công thức Nhà cung cấp khi bạn muốn hiển thị API cho cấu hình toàn ứng dụng phải được thực hiện trước khi ứng dụng bắt đầu. Điều này thường chỉ thú vị đối với các dịch vụ có thể sử dụng lại mà hành vi của chúng có thể cần thay đổi đôi chút giữa các ứng dụng.
decorator
.Hiểu nhà máy, dịch vụ và nhà cung cấp AngularJS
Tất cả những thứ này được sử dụng để chia sẻ các đối tượng singleton có thể tái sử dụng. Nó giúp chia sẻ mã có thể sử dụng lại trên ứng dụng / các thành phần / mô-đun khác nhau của bạn.
Từ Dịch vụ / Nhà máy Docs :
- Khởi tạo nhanh chóng - Angular chỉ khởi tạo một dịch vụ / nhà máy khi một thành phần ứng dụng phụ thuộc vào nó.
- Singletons - Mỗi thành phần phụ thuộc vào một dịch vụ sẽ tham chiếu đến một thể hiện duy nhất được tạo bởi nhà máy dịch vụ.
Một nhà máy là chức năng nơi bạn có thể thao tác / thêm logic trước khi tạo một đối tượng, sau đó đối tượng mới được tạo sẽ được trả về.
app.factory('MyFactory', function() {
var serviceObj = {};
//creating an object with methods/functions or variables
serviceObj.myFunction = function() {
//TO DO:
};
//return that object
return serviceObj;
});
Sử dụng
Nó có thể chỉ là một tập hợp các hàm như một lớp. Do đó, nó có thể được khởi tạo trong các bộ điều khiển khác nhau khi bạn tiêm nó vào bên trong các chức năng điều khiển / nhà máy / chỉ thị của bạn. Nó được khởi tạo chỉ một lần cho mỗi ứng dụng.
Đơn giản là trong khi nhìn vào các dịch vụ nghĩ về nguyên mẫu mảng. Dịch vụ là một chức năng khởi tạo một đối tượng mới bằng cách sử dụng từ khóa 'mới'. Bạn có thể thêm các thuộc tính và chức năng cho một đối tượng dịch vụ bằng cách sử dụng this
từ khóa. Không giống như một nhà máy, nó không trả về bất cứ thứ gì (nó trả về một đối tượng có chứa các phương thức / thuộc tính).
app.service('MyService', function() {
//directly binding events to this context
this.myServiceFunction = function() {
//TO DO:
};
});
Sử dụng
Sử dụng nó khi bạn cần chia sẻ một đối tượng trong suốt ứng dụng. Ví dụ: chi tiết người dùng được xác thực, phương pháp / dữ liệu có thể chia sẻ, chức năng Utility, v.v.
Một nhà cung cấp được sử dụng để tạo một đối tượng dịch vụ có thể cấu hình. Bạn có thể định cấu hình cài đặt dịch vụ từ chức năng cấu hình. Nó trả về một giá trị bằng cách sử dụng $get()
hàm. Các $get
chức năng được thực hiện vào giai đoạn chạy trong góc.
app.provider('configurableService', function() {
var name = '';
//this method can be be available at configuration time inside app.config.
this.setName = function(newName) {
name = newName;
};
this.$get = function() {
var getName = function() {
return name;
};
return {
getName: getName //exposed object to where it gets injected.
};
};
});
Sử dụng
Khi bạn cần cung cấp cấu hình mô-đun cho đối tượng dịch vụ của mình trước khi cung cấp nó, vd. giả sử bạn muốn đặt URL API trên cơ sở Môi trường của bạn như dev
, stage
hoặcprod
GHI CHÚ
Chỉ nhà cung cấp sẽ có sẵn trong giai đoạn cấu hình của góc, trong khi dịch vụ & nhà máy thì không.
Hy vọng điều này đã làm sáng tỏ sự hiểu biết của bạn về Nhà máy, Dịch vụ và Nhà cung cấp .
only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications
, vì vậy không có âm thanh, phải không?
Đối với tôi, sự mặc khải đến khi tôi nhận ra rằng tất cả chúng đều hoạt động theo cùng một cách: bằng cách chạy một cái gì đó một lần , lưu trữ giá trị họ nhận được, và sau đó ho lên cùng một giá trị được lưu trữ khi được tham chiếu thông qua tiêm phụ thuộc .
Nói rằng chúng tôi có:
app.factory('a', fn);
app.service('b', fn);
app.provider('c', fn);
Sự khác biệt giữa ba là:
a
Giá trị được lưu trữ đến từ việc chạy fn
.b
Giá trị được lưu trữ đến từ new
ing fn
.c
'giá trị s lưu trữ xuất phát từ đầu tiên nhận được một thể hiện bởi new
ing fn
, và sau đó chạy một $get
phương pháp sơ thẩm.Điều đó có nghĩa là có một cái gì đó giống như một đối tượng bộ đệm trong AngularJS, giá trị của mỗi lần tiêm chỉ được gán một lần, khi chúng được tiêm lần đầu tiên và ở đâu:
cache.a = fn()
cache.b = new fn()
cache.c = (new fn()).$get()
Đây là lý do tại sao chúng tôi sử dụng this
trong các dịch vụ và xác định một this.$get
trong các nhà cung cấp.
factory
s. Lý do duy nhất service
tồn tại là các ngôn ngữ như CoffeeScript, TypeScript, ES6, v.v. để bạn có thể sử dụng cú pháp lớp của chúng. Bạn chỉ cần provider
s nếu mô-đun của bạn được sử dụng trong một số ứng dụng với các cài đặt khác nhau bằng cách sử dụng app.config()
. Nếu dịch vụ của bạn là một singleton thuần túy hoặc có thể tạo các phiên bản của một cái gì đó chỉ phụ thuộc vào việc triển khai của bạn.
Dịch vụ vs nhà cung cấp vs nhà máy:
Tôi đang cố gắng để giữ cho nó đơn giản. Đó là tất cả về khái niệm JavaScript cơ bản.
Trước hết, hãy nói về các dịch vụ trong AngularJS!
Dịch vụ là gì: Trong AngularJS, Dịch vụkhông là gì ngoài một đối tượng JavaScript đơn lẻ có thể lưu trữ một số phương thức hoặc thuộc tính hữu ích. Đối tượng singleton này được tạo trên cơ sở ngApp (ứng dụng Angular) và nó được chia sẻ giữa tất cả các bộ điều khiển trong ứng dụng hiện tại. Khi Angularjs khởi tạo một đối tượng dịch vụ, nó đăng ký đối tượng dịch vụ này với một tên dịch vụ duy nhất. Vì vậy, mỗi khi chúng ta cần phiên bản dịch vụ, Angular tìm kiếm sổ đăng ký cho tên dịch vụ này và nó trả về tham chiếu đến đối tượng dịch vụ. Để chúng ta có thể gọi phương thức, truy cập các thuộc tính, vv trên đối tượng dịch vụ. Bạn có thể có câu hỏi liệu bạn cũng có thể đặt các thuộc tính, phương thức vào đối tượng phạm vi của bộ điều khiển! Vậy tại sao bạn cần đối tượng dịch vụ? Câu trả lời là: dịch vụ được chia sẻ giữa nhiều phạm vi điều khiển. Nếu bạn đặt một số thuộc tính / phương thức trong đối tượng phạm vi của bộ điều khiển, nó sẽ chỉ khả dụng cho phạm vi hiện tại.
Vì vậy, nếu có ba phạm vi điều khiển, hãy để nó là bộ điều khiểnA, bộ điều khiểnB và bộ điều khiển, tất cả sẽ chia sẻ cùng một thể hiện dịch vụ.
<div ng-controller='controllerA'>
<!-- controllerA scope -->
</div>
<div ng-controller='controllerB'>
<!-- controllerB scope -->
</div>
<div ng-controller='controllerC'>
<!-- controllerC scope -->
</div>
Làm thế nào để tạo ra một dịch vụ?
AngularJS cung cấp các phương pháp khác nhau để đăng ký một dịch vụ. Ở đây chúng tôi sẽ tập trung vào ba phương thức nhà máy (..), dịch vụ (..), nhà cung cấp (..);
Sử dụng liên kết này để tham khảo mã
Chúng ta có thể định nghĩa một chức năng nhà máy như dưới đây.
factory('serviceName',function fnFactory(){ return serviceInstance;})
AngularJS cung cấp phương thức 'Factory (' serviceName ', fnFactory)' trong đó có hai tham số, serviceName và hàm JavaScript. Angular tạo cá thể dịch vụ bằng cách gọi hàm fnFactory () như bên dưới.
var serviceInstace = fnFactory();
Hàm thông qua có thể định nghĩa một đối tượng và trả về đối tượng đó. AngularJS chỉ lưu trữ tham chiếu đối tượng này đến một biến được truyền dưới dạng đối số đầu tiên. Bất cứ điều gì được trả về từ fnFactory sẽ bị ràng buộc với serviceInstance. Thay vì trả về đối tượng, chúng ta cũng có thể trả về hàm, các giá trị, v.v., Dù chúng ta sẽ trả về, sẽ có sẵn cho thể hiện dịch vụ.
Thí dụ:
var app= angular.module('myApp', []);
//creating service using factory method
app.factory('factoryPattern',function(){
var data={
'firstName':'Tom',
'lastName':' Cruise',
greet: function(){
console.log('hello!' + this.firstName + this.lastName);
}
};
//Now all the properties and methods of data object will be available in our service object
return data;
});
service('serviceName',function fnServiceConstructor(){})
Đó là một cách khác, chúng ta có thể đăng ký một dịch vụ. Sự khác biệt duy nhất là cách AngularJS cố gắng khởi tạo đối tượng dịch vụ. Lần này góc sử dụng từ khóa 'mới' và gọi hàm xây dựng một cái gì đó như dưới đây.
var serviceInstance = new fnServiceConstructor();
Trong hàm constructor, chúng ta có thể sử dụng từ khóa 'this' để thêm thuộc tính / phương thức vào đối tượng dịch vụ. thí dụ:
//Creating a service using the service method
var app= angular.module('myApp', []);
app.service('servicePattern',function(){
this.firstName ='James';
this.lastName =' Bond';
this.greet = function(){
console.log('My Name is '+ this.firstName + this.lastName);
};
});
Hàm Carrier () là một cách khác để tạo dịch vụ. Hãy để chúng tôi quan tâm để tạo ra một dịch vụ chỉ hiển thị một số thông điệp chào mừng đến người dùng. Nhưng chúng tôi cũng muốn cung cấp một chức năng để người dùng có thể đặt thông điệp chào mừng của riêng họ. Về mặt kỹ thuật, chúng tôi muốn tạo ra các dịch vụ cấu hình. Làm thế nào chúng ta có thể làm điều này ? Phải có một cách để ứng dụng có thể chuyển thông điệp chào hỏi tùy chỉnh của họ và Angularjs sẽ cung cấp cho chức năng nhà máy / nhà xây dựng tạo ra thể hiện dịch vụ của chúng tôi. Trong trường hợp như vậy, hàm cung cấp () thực hiện công việc. sử dụng hàm nhà cung cấp () chúng ta có thể tạo các dịch vụ cấu hình.
Chúng tôi có thể tạo các dịch vụ có thể định cấu hình bằng cú pháp của nhà cung cấp như được đưa ra dưới đây.
/*step1:define a service */
app.provider('service',function serviceProviderConstructor(){});
/*step2:configure the service */
app.config(function configureService(serviceProvider){});
Đối tượng 1.Provider được tạo bằng hàm constructor mà chúng ta đã định nghĩa trong hàm nhà cung cấp.
var serviceProvider = new serviceProviderConstructor();
2. Hàm chúng ta đã truyền trong app.config (), được thực thi. Đây được gọi là giai đoạn cấu hình và ở đây chúng tôi có cơ hội tùy chỉnh dịch vụ của mình.
configureService(serviceProvider);
3. Ví dụ dịch vụ cuối cùng được tạo bằng cách gọi phương thức $ get của serviceProvider.
serviceInstance = serviceProvider.$get()
var app= angular.module('myApp', []);
app.provider('providerPattern',function providerConstructor(){
//this function works as constructor function for provider
this.firstName = 'Arnold ';
this.lastName = ' Schwarzenegger' ;
this.greetMessage = ' Welcome, This is default Greeting Message' ;
//adding some method which we can call in app.config() function
this.setGreetMsg = function(msg){
if(msg){
this.greetMessage = msg ;
}
};
//We can also add a method which can change firstName and lastName
this.$get = function(){
var firstName = this.firstName;
var lastName = this.lastName ;
var greetMessage = this.greetMessage;
var data={
greet: function(){
console.log('hello, ' + firstName + lastName+'! '+ greetMessage);
}
};
return data ;
};
});
app.config(
function(providerPatternProvider){
providerPatternProvider.setGreetMsg(' How do you do ?');
}
);
Tóm lược:
Nhà máy sử dụng chức năng của nhà máy trả về một thể hiện dịch vụ. serviceInstance = fnFactory ();
Dịch vụ sử dụng hàm xây dựng và Angular gọi hàm xây dựng này bằng từ khóa 'mới' để tạo phiên bản dịch vụ. serviceInstance = new fnServiceConstructor ();
Nhà cung cấp xác định chức năng của nhà cung cấp, công cụ của nhà cung cấp này cung cấp chức năng nhà máy $ get . Angular gọi $ get () để tạo đối tượng dịch vụ. Cú pháp của nhà cung cấp có thêm lợi thế là cấu hình đối tượng dịch vụ trước khi được khởi tạo. serviceInstance = $ get ();
Như được chỉ ra bởi một số người ở đây một cách chính xác một nhà máy, nhà cung cấp, dịch vụ và thậm chí giá trị và hằng số là các phiên bản của cùng một thứ. Bạn có thể mổ xẻ tổng quát hơn provider
vào tất cả chúng. Thích như vậy:
Đây là bài viết hình ảnh này là từ:
Bạn cung cấp cho AngularJS một chức năng, AngularJS sẽ lưu trữ và chèn giá trị trả về khi nhà máy được yêu cầu.
Thí dụ:
app.factory('factory', function() {
var name = '';
// Return value **is** the object that will be injected
return {
name: name;
}
})
Sử dụng:
app.controller('ctrl', function($scope, factory) {
$scope.name = factory.name;
});
Bạn cung cấp cho AngularJS một chức năng, AngularJS sẽ gọi mới để khởi tạo nó. Đó là ví dụ mà AngularJS tạo ra sẽ được lưu trữ và chèn vào khi dịch vụ được yêu cầu. Vì mới được sử dụng để khởi tạo dịch vụ, từ khóa này là hợp lệ và đề cập đến thể hiện.
Thí dụ:
app.service('service', function() {
var name = '';
this.setName = function(newName) {
name = newName;
}
this.getName = function() {
return name;
}
});
Sử dụng:
app.controller('ctrl', function($scope, service) {
$scope.name = service.getName();
});
Bạn cung cấp cho AngularJS một chức năng và AngularJS sẽ gọi $get
chức năng của nó . Đó là giá trị trả về từ $get
hàm sẽ được lưu trữ và được chèn khi dịch vụ được yêu cầu.
Các nhà cung cấp cho phép bạn định cấu hình nhà cung cấp trước khi AngularJS gọi $get
phương thức để có được tiêm.
Thí dụ:
app.provider('provider', function() {
var name = '';
this.setName = function(newName) {
name = newName;
}
this.$get = function() {
return {
name: name
}
}
})
Cách sử dụng (dưới dạng tiêm trong bộ điều khiển)
app.controller('ctrl', function($scope, provider) {
$scope.name = provider.name;
});
Cách sử dụng (cấu hình nhà cung cấp trước $get
được gọi để tạo ra tiêm)
app.config(function(providerProvider) {
providerProvider.setName('John');
});
Tôi nhận thấy một điều thú vị khi chơi xung quanh với các nhà cung cấp.
Tầm nhìn của thuốc tiêm là khác nhau đối với các nhà cung cấp so với các dịch vụ và nhà máy. Nếu bạn khai báo "hằng số" AngularJS (ví dụ myApp.constant('a', 'Robert');
:), bạn có thể đưa nó vào các dịch vụ, nhà máy và nhà cung cấp.
Nhưng nếu bạn khai báo "giá trị" AngularJS (ví dụ., myApp.value('b', {name: 'Jones'});
), Bạn có thể đưa nó vào các dịch vụ và nhà máy, nhưng KHÔNG vào chức năng tạo nhà cung cấp. Tuy nhiên, bạn có thể đưa nó vào $get
chức năng mà bạn xác định cho nhà cung cấp của mình. Điều này được đề cập trong tài liệu AngularJS, nhưng nó rất dễ bỏ lỡ. Bạn có thể tìm thấy nó trên trang% cung cấp trong các phần về các phương thức giá trị và hằng số.
<div ng-app="MyAppName">
<div ng-controller="MyCtrl">
<p>from Service: {{servGreet}}</p>
<p>from Provider: {{provGreet}}</p>
</div>
</div>
<script>
var myApp = angular.module('MyAppName', []);
myApp.constant('a', 'Robert');
myApp.value('b', {name: 'Jones'});
myApp.service('greetService', function(a,b) {
this.greeter = 'Hi there, ' + a + ' ' + b.name;
});
myApp.provider('greetProvider', function(a) {
this.firstName = a;
this.$get = function(b) {
this.lastName = b.name;
this.fullName = this.firstName + ' ' + this.lastName;
return this;
};
});
function MyCtrl($scope, greetService, greetProvider) {
$scope.servGreet = greetService.greeter;
$scope.provGreet = greetProvider.fullName;
}
</script>
Đây là một phần rất khó hiểu đối với người mới và tôi đã cố gắng làm rõ nó bằng những từ dễ dàng
AngularJS Service: được sử dụng để chia sẻ các chức năng tiện ích với tham chiếu dịch vụ trong bộ điều khiển. Dịch vụ là bản chất đơn lẻ vì vậy đối với một dịch vụ chỉ có một phiên bản được tạo trong trình duyệt và cùng một tham chiếu được sử dụng trên toàn trang.
Trong dịch vụ, chúng ta tạo các tên hàm làm thuộc tính với đối tượng này .
AngularJS Factory: mục đích của Factory cũng giống như Service, tuy nhiên trong trường hợp này chúng tôi tạo một đối tượng mới và thêm các hàm làm thuộc tính của đối tượng này và cuối cùng chúng tôi trả lại đối tượng này.
Nhà cung cấp AngularJS: mục đích của việc này lại giống nhau tuy nhiên Nhà cung cấp đưa ra đầu ra của hàm $ get.
Xác định và sử dụng Dịch vụ, Nhà máy và Nhà cung cấp được giải thích tại http://www.dotnetfunda.com/articles/show/3156/difference-b between-angularjs-service-fact-and-proider
Đối với tôi cách tốt nhất và đơn giản nhất để hiểu sự khác biệt là:
var service, factory;
service = factory = function(injection) {}
Cách AngularJS khởi tạo các thành phần cụ thể (đơn giản hóa):
// service
var angularService = new service(injection);
// factory
var angularFactory = factory(injection);
Vì vậy, đối với dịch vụ, thành phần AngularJS trở thành đối tượng của lớp được đại diện bởi hàm khai báo dịch vụ. Đối với nhà máy, đó là kết quả trả về từ chức năng khai báo của nhà máy. Nhà máy có thể hoạt động giống như dịch vụ:
var factoryAsService = function(injection) {
return new function(injection) {
// Service content
}
}
Cách suy nghĩ đơn giản nhất là cách sau:
Ví dụ về 'lớp' của nhà máy được cung cấp trong các ý kiến xung quanh, cũng như sự khác biệt của nhà cung cấp.
new MyService()
hoặc một cái gì đó :)
Làm rõ của tôi về vấn đề này:
Về cơ bản, tất cả các loại được đề cập (dịch vụ, nhà máy, nhà cung cấp, v.v.) chỉ đang tạo và định cấu hình các biến toàn cục (tất nhiên là toàn cầu cho toàn bộ ứng dụng), giống như các biến toàn cầu kiểu cũ.
Mặc dù các biến toàn cục không được khuyến nghị, việc sử dụng thực sự của các biến toàn cục này là để cung cấp nội xạ phụ thuộc , bằng cách chuyển biến cho bộ điều khiển có liên quan.
Có nhiều mức độ phức tạp trong việc tạo các giá trị cho "biến toàn cục":
app.config
.
app.config
tệp và hàm $ .get này hoạt động giống như nhà máy ở trên, trong đó giá trị trả về của nó được sử dụng để khởi tạo các biến "toàn cầu". Hiểu biết của tôi rất đơn giản dưới đây.
Factory: Bạn chỉ cần tạo một đối tượng bên trong nhà máy và trả lại nó.
Dịch vụ:
Bạn chỉ có một hàm tiêu chuẩn sử dụng từ khóa này để xác định hàm.
Các nhà cung cấp:
Có một $get
đối tượng mà bạn xác định và nó có thể được sử dụng để lấy đối tượng trả về dữ liệu.
Tóm tắt từ các tài liệu Angular :
Câu trả lời hay nhất từ SO:
https://stackoverflow.com/a/26924234/165673 (<- TỐT)
https://stackoverflow.com/a/27263882/165673
https://stackoverflow.com/a/16566144/165673
Tất cả các câu trả lời tốt rồi. Tôi muốn thêm vài điểm nữa về Dịch vụ và Nhà máy . Cùng với sự khác biệt giữa dịch vụ / nhà máy. Và người ta cũng có thể có những câu hỏi như:
Hãy bắt đầu với sự khác biệt giữa Dịch vụ và nhà máy:
Cả hai đều là Singletons : Bất cứ khi nào Angular lần đầu tiên tìm thấy chúng như một sự phụ thuộc, nó sẽ tạo ra một thể hiện duy nhất của dịch vụ / nhà máy. Khi cá thể được tạo, cùng một thể hiện được sử dụng mãi mãi.
Có thể được sử dụng để mô hình hóa một đối tượng với hành vi : Cả hai đều có thể có các phương thức, các biến trạng thái bên trong, v.v. Mặc dù cách bạn viết mã đó sẽ khác nhau.
Dịch vụ:
Một dịch vụ là một hàm tạo, và Angular sẽ khởi tạo nó bằng cách gọi mới yourServiceName()
. Điều này có nghĩa là một vài điều.
this
.new yourServiceName(
), nó sẽ nhận được this
đối tượng với tất cả các thuộc tính bạn đặt trên nó.Ví dụ mẫu:
angular.service('MyService', function() {
this.aServiceVariable = "Ved Prakash"
this.aServiceMethod = function() {
return //code
};
});
Khi Angular đưa
MyService
dịch vụ này vào một bộ điều khiển phụ thuộc vào nó, bộ điều khiển đó sẽ nhận được mộtMyService
chức năng mà nó có thể gọi các hàm trên, ví dụ MyService.aServiceMethod ().
Hãy cẩn thận vớithis
:
Vì dịch vụ được xây dựng là một đối tượng, nên các phương thức bên trong nó có thể tham chiếu đến điều này khi chúng được gọi:
angular.service('ScoreKeeper', function($http) {
this.score = 0;
this.getScore = function() {
return this.score;
};
this.setScore = function(newScore) {
this.score = newScore;
};
this.addOne = function() {
this.score++;
};
});
ScoreKeeper.setScore
Chẳng hạn, bạn có thể muốn gọi một chuỗi lời hứa, nếu bạn đã khởi tạo điểm số bằng cách lấy nó từ máy chủ: $http.get('/score').then(ScoreKeeper.setScore).
Vấn đề với điều này là ScoreKeeper.setScore
sẽ this
bị ràng buộc null
và bạn sẽ gặp lỗi. Cách tốt hơn sẽ là $http.get('/score').then(ScoreKeeper.setScore.bind(ScoreKeeper))
. Cho dù bạn có chọn sử dụng điều này trong phương thức dịch vụ của mình hay không, hãy cẩn thận với cách bạn gọi chúng.
Trả lại một giá trị từ mộtService
:
Do cách các hàm tạo JavaScript hoạt động, nếu bạn trả về một giá trị phức tạp (i.e., an Object)
từ một constructor
hàm, người gọi sẽ nhận được Đối tượng đó thay vì thể hiện này.
Điều này có nghĩa là về cơ bản bạn có thể sao chép-dán ví dụ về nhà máy từ bên dưới, thay thế factory
bằng service
và nó sẽ hoạt động:
angular.service('MyService', function($http) {
var api = {};
api.aServiceMethod= function() {
return $http.get('/users');
};
return api;
});
Vì vậy, khi Angular xây dựng dịch vụ của bạn với MyService () mới, nó sẽ nhận được đối tượng api đó thay vì đối tượng MyService.
Đây là hành vi cho bất kỳ giá trị phức tạp (đối tượng, hàm) nhưng không dành cho các kiểu nguyên thủy.
Các nhà máy:
Một nhà máy là một hàm cũ đơn giản trả về một giá trị. Giá trị trả lại là những gì được đưa vào những thứ phụ thuộc vào nhà máy. Một mô hình nhà máy điển hình trong Angular là trả về một đối tượng có chức năng là các thuộc tính, như thế này:
angular.factory('MyFactory', function($http) {
var api = {};
api.aFactoryMethod= function() {
return $http.get('/users');
};
return api;
});
Giá trị được tiêm cho một phụ thuộc của nhà máy là giá trị trả về của nhà máy và nó không phải là một đối tượng. Nó có thể là một chức năng
Câu trả lời cho 1 và 2 câu hỏi trên:
Đối với hầu hết các phần, chỉ cần gắn bó với việc sử dụng các nhà máy cho tất cả mọi thứ. Hành vi của họ dễ hiểu hơn. Không có lựa chọn nào về việc có nên trả lại giá trị hay không, và hơn nữa, không có lỗi nào được đưa ra nếu bạn làm sai.
Mặc dù vậy, tôi vẫn gọi chúng là dịch vụ của người Hồi giáo khi tôi nói về việc tiêm chúng như là phụ thuộc.
Hành vi dịch vụ / nhà máy rất giống nhau và một số người sẽ nói rằng một trong hai là tốt. Điều đó hơi đúng, nhưng tôi thấy dễ dàng hơn khi làm theo lời khuyên của hướng dẫn phong cách của John Papa và chỉ cần gắn bó với các nhà máy. **
Một sự làm rõ bổ sung là các nhà máy có thể tạo ra các chức năng / nguyên thủy, trong khi các dịch vụ thì không thể. Hãy xem jsFiddle này dựa trên Epokk's: http://jsfiddle.net/skeller88/PxdSP/1351/ .
Nhà máy trả về một hàm có thể được gọi:
myApp.factory('helloWorldFromFactory', function() {
return function() {
return "Hello, World!";
};
});
Nhà máy cũng có thể trả về một đối tượng bằng một phương thức có thể được gọi:
myApp.factory('helloWorldFromFactory', function() {
return {
sayHello: function() {
return "Hello, World!";
}
};
});
Dịch vụ trả về một đối tượng với một phương thức có thể được gọi:
myApp.service('helloWorldFromService', function() {
this.sayHello = function() {
return "Hello, World!";
};
});
Để biết thêm chi tiết, hãy xem bài đăng tôi đã viết về sự khác biệt: http://www.shanemkeller.com/tldr-service-vs-factories-in-angular/
Đã có câu trả lời tốt, nhưng tôi chỉ muốn chia sẻ câu hỏi này.
Trước hết: Nhà cung cấp là cách / công thức để tạo ra một service
(đối tượng singleton) giả sử được tiêm bởi $ kim phun (cách AngulaJS đi về mô hình IoC).
Và Giá trị, Nhà máy, Dịch vụ và Hằng số (4 cách) - đường cú pháp trên cách cung cấp / recepie của Nhà cung cấp .
Có Service vs Factory
một phần đã được bảo hiểm:
https://www.youtube.com/watch?v=BLzNCkPn3ao
Dịch vụ là tất cả về new
từ khóa mà như chúng ta biết có 4 điều:
prototype
đối tượng của nócontext
vớithis
this
Và Factory là tất cả về Mô hình nhà máy - chứa các hàm trả về các Đối tượng như Dịch vụ đó.
Và video đơn giản / ngắn này: bao gồm cả Nhà cung cấp : https://www.youtube.com/watch?v=HvTZbQ_hUZY (ở đó bạn thấy có thể thấy cách họ đi từ nhà máy đến nhà cung cấp)
Công thức của nhà cung cấp được sử dụng chủ yếu trong cấu hình ứng dụng, trước khi ứng dụng hoàn toàn khởi động / khởi tạo.
Sau khi đọc tất cả các bài đăng này Nó tạo ra nhiều nhầm lẫn cho tôi .. Nhưng tất cả vẫn là thông tin đáng giá .. cuối cùng tôi đã tìm thấy bảng sau đây sẽ cung cấp thông tin với sự so sánh đơn giản
Và cho người mới bắt đầu hiểu: - Điều này có thể không đúng trường hợp sử dụng nhưng ở cấp độ cao đây là những gì usecase cho ba.
angular.module('myApp').config(function($testProvider){
$testProvider.someFunction();
})
Đối với các kịch bản cơ bản, nhà máy và dịch vụ hoạt động như nhau.
Dưới đây là một số mã trình biên dịch mà tôi đã đưa ra dưới dạng mẫu mã cho nhà máy đối tượng trong AngularjS. Tôi đã sử dụng Car / CarFactory làm ví dụ để minh họa. Làm cho mã thực hiện đơn giản trong bộ điều khiển.
<script>
angular.module('app', [])
.factory('CarFactory', function() {
/**
* BroilerPlate Object Instance Factory Definition / Example
*/
this.Car = function() {
// initialize instance properties
angular.extend(this, {
color : null,
numberOfDoors : null,
hasFancyRadio : null,
hasLeatherSeats : null
});
// generic setter (with optional default value)
this.set = function(key, value, defaultValue, allowUndefined) {
// by default,
if (typeof allowUndefined === 'undefined') {
// we don't allow setter to accept "undefined" as a value
allowUndefined = false;
}
// if we do not allow undefined values, and..
if (!allowUndefined) {
// if an undefined value was passed in
if (value === undefined) {
// and a default value was specified
if (defaultValue !== undefined) {
// use the specified default value
value = defaultValue;
} else {
// otherwise use the class.prototype.defaults value
value = this.defaults[key];
} // end if/else
} // end if
} // end if
// update
this[key] = value;
// return reference to this object (fluent)
return this;
}; // end this.set()
}; // end this.Car class definition
// instance properties default values
this.Car.prototype.defaults = {
color: 'yellow',
numberOfDoors: 2,
hasLeatherSeats: null,
hasFancyRadio: false
};
// instance factory method / constructor
this.Car.prototype.instance = function(params) {
return new
this.constructor()
.set('color', params.color)
.set('numberOfDoors', params.numberOfDoors)
.set('hasFancyRadio', params.hasFancyRadio)
.set('hasLeatherSeats', params.hasLeatherSeats)
;
};
return new this.Car();
}) // end Factory Definition
.controller('testCtrl', function($scope, CarFactory) {
window.testCtrl = $scope;
// first car, is red, uses class default for:
// numberOfDoors, and hasLeatherSeats
$scope.car1 = CarFactory
.instance({
color: 'red'
})
;
// second car, is blue, has 3 doors,
// uses class default for hasLeatherSeats
$scope.car2 = CarFactory
.instance({
color: 'blue',
numberOfDoors: 3
})
;
// third car, has 4 doors, uses class default for
// color and hasLeatherSeats
$scope.car3 = CarFactory
.instance({
numberOfDoors: 4
})
;
// sets an undefined variable for 'hasFancyRadio',
// explicitly defines "true" as default when value is undefined
$scope.hasFancyRadio = undefined;
$scope.car3.set('hasFancyRadio', $scope.hasFancyRadio, true);
// fourth car, purple, 4 doors,
// uses class default for hasLeatherSeats
$scope.car4 = CarFactory
.instance({
color: 'purple',
numberOfDoors: 4
});
// and then explicitly sets hasLeatherSeats to undefined
$scope.hasLeatherSeats = undefined;
$scope.car4.set('hasLeatherSeats', $scope.hasLeatherSeats, undefined, true);
// in console, type window.testCtrl to see the resulting objects
});
</script>
Đây là một ví dụ đơn giản hơn. Tôi đang sử dụng một vài thư viện bên thứ ba mong muốn một đối tượng "Vị trí" phơi bày vĩ độ và kinh độ, nhưng thông qua các thuộc tính đối tượng khác nhau. Tôi không muốn hack mã nhà cung cấp, vì vậy tôi đã điều chỉnh các đối tượng "Vị trí" mà tôi đang đi qua.
angular.module('app')
.factory('PositionFactory', function() {
/**
* BroilerPlate Object Instance Factory Definition / Example
*/
this.Position = function() {
// initialize instance properties
// (multiple properties to satisfy multiple external interface contracts)
angular.extend(this, {
lat : null,
lon : null,
latitude : null,
longitude : null,
coords: {
latitude: null,
longitude: null
}
});
this.setLatitude = function(latitude) {
this.latitude = latitude;
this.lat = latitude;
this.coords.latitude = latitude;
return this;
};
this.setLongitude = function(longitude) {
this.longitude = longitude;
this.lon = longitude;
this.coords.longitude = longitude;
return this;
};
}; // end class definition
// instance factory method / constructor
this.Position.prototype.instance = function(params) {
return new
this.constructor()
.setLatitude(params.latitude)
.setLongitude(params.longitude)
;
};
return new this.Position();
}) // end Factory Definition
.controller('testCtrl', function($scope, PositionFactory) {
$scope.position1 = PositionFactory.instance({latitude: 39, longitude: 42.3123});
$scope.position2 = PositionFactory.instance({latitude: 39, longitude: 42.3333});
}) // end controller
;
Sử dụng làm tài liệu tham khảo trang này và tài liệu (dường như đã được cải thiện rất nhiều kể từ lần cuối tôi xem), tôi đã kết hợp bản demo thế giới thực (-ish) sau đây sử dụng 4 trong 5 hương vị của nhà cung cấp; Giá trị, liên tục, nhà máy và nhà cung cấp đầy đủ thổi.
HTML:
<div ng-controller="mainCtrl as main">
<h1>{{main.title}}*</h1>
<h2>{{main.strapline}}</h2>
<p>Earn {{main.earn}} per click</p>
<p>You've earned {{main.earned}} by clicking!</p>
<button ng-click="main.handleClick()">Click me to earn</button>
<small>* Not actual money</small>
</div>
ứng dụng
var app = angular.module('angularProviders', []);
// A CONSTANT is not going to change
app.constant('range', 100);
// A VALUE could change, but probably / typically doesn't
app.value('title', 'Earn money by clicking');
app.value('strapline', 'Adventures in ng Providers');
// A simple FACTORY allows us to compute a value @ runtime.
// Furthermore, it can have other dependencies injected into it such
// as our range constant.
app.factory('random', function randomFactory(range) {
// Get a random number within the range defined in our CONSTANT
return Math.random() * range;
});
// A PROVIDER, must return a custom type which implements the functionality
// provided by our service (see what I did there?).
// Here we define the constructor for the custom type the PROVIDER below will
// instantiate and return.
var Money = function(locale) {
// Depending on locale string set during config phase, we'll
// use different symbols and positioning for any values we
// need to display as currency
this.settings = {
uk: {
front: true,
currency: '£',
thousand: ',',
decimal: '.'
},
eu: {
front: false,
currency: '€',
thousand: '.',
decimal: ','
}
};
this.locale = locale;
};
// Return a monetary value with currency symbol and placement, and decimal
// and thousand delimiters according to the locale set in the config phase.
Money.prototype.convertValue = function(value) {
var settings = this.settings[this.locale],
decimalIndex, converted;
converted = this.addThousandSeparator(value.toFixed(2), settings.thousand);
decimalIndex = converted.length - 3;
converted = converted.substr(0, decimalIndex) +
settings.decimal +
converted.substr(decimalIndex + 1);
converted = settings.front ?
settings.currency + converted :
converted + settings.currency;
return converted;
};
// Add supplied thousand separator to supplied value
Money.prototype.addThousandSeparator = function(value, symbol) {
return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, symbol);
};
// PROVIDER is the core recipe type - VALUE, CONSTANT, SERVICE & FACTORY
// are all effectively syntactic sugar built on top of the PROVIDER construct
// One of the advantages of the PROVIDER is that we can configure it before the
// application starts (see config below).
app.provider('money', function MoneyProvider() {
var locale;
// Function called by the config to set up the provider
this.setLocale = function(value) {
locale = value;
};
// All providers need to implement a $get method which returns
// an instance of the custom class which constitutes the service
this.$get = function moneyFactory() {
return new Money(locale);
};
});
// We can configure a PROVIDER on application initialisation.
app.config(['moneyProvider', function(moneyProvider) {
moneyProvider.setLocale('uk');
//moneyProvider.setLocale('eu');
}]);
// The ubiquitous controller
app.controller('mainCtrl', function($scope, title, strapline, random, money) {
// Plain old VALUE(s)
this.title = title;
this.strapline = strapline;
this.count = 0;
// Compute values using our money provider
this.earn = money.convertValue(random); // random is computed @ runtime
this.earned = money.convertValue(0);
this.handleClick = function() {
this.count ++;
this.earned = money.convertValue(random * this.count);
};
});
Bản demo làm việc .
Câu trả lời này giải quyết chủ đề / câu hỏi
HOẶC LÀ
về cơ bản những gì xảy ra là
Khi bạn tạo một factory()
bộ, bạn function
đã cung cấp trong đối số thứ hai cho nhà cung cấp $get
và trả lại ( provider(name, {$get:factoryFn })
), tất cả những gì bạn nhận được làprovider
nhưng không có thuộc tính / phương thức nào khác ngoài$get
điều đó provider
(có nghĩa là bạn không thể định cấu hình này)
Mã nguồn của nhà máy
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
};
Khi thực hiện service()
trả lại, bạn cung cấp cho nhà máy () mộtfunction
tiêm constructor
(trả lại thể hiện của hàm tạo mà bạn đã cung cấp trong dịch vụ của mình) và trả về
Mã nguồn của dịch vụ
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
};
Vì vậy, về cơ bản trong cả hai trường hợp, cuối cùng bạn sẽ nhận được một nhà cung cấp $ get set cho chức năng của bạn mà bạn đã cung cấp, nhưng bạn có thể cung cấp bất cứ thứ gì ngoài $ get như ban đầu bạn có thể cung cấp trong nhà cung cấp () cho khối cấu hình
Tôi biết rất nhiều câu trả lời xuất sắc nhưng tôi phải chia sẻ kinh nghiệm sử dụng
1. service
trong hầu hết các trường hợp mặc định
2. factory
được sử dụng để tạo ra dịch vụ cụ thể đó
// factory.js ////////////////////////////
(function() {
'use strict';
angular
.module('myApp.services')
.factory('xFactory', xFactoryImp);
xFactoryImp.$inject = ['$http'];
function xFactoryImp($http) {
var fac = function (params) {
this._params = params; // used for query params
};
fac.prototype.nextPage = function () {
var url = "/_prc";
$http.get(url, {params: this._params}).success(function(data){ ...
}
return fac;
}
})();
// service.js //////////////////////////
(function() {
'use strict';
angular
.module('myApp.services')
.service('xService', xServiceImp);
xServiceImp.$inject = ['$http'];
function xServiceImp($http) {
this._params = {'model': 'account','mode': 'list'};
this.nextPage = function () {
var url = "/_prc";
$http.get(url, {params: this._params}).success(function(data){ ...
}
}
})();
và sử dụng:
controller: ['xFactory', 'xService', function(xFactory, xService){
// books = new instance of xFactory for query 'book' model
var books = new xFactory({'model': 'book', 'mode': 'list'});
// accounts = new instance of xFactory for query 'accounts' model
var accounts = new xFactory({'model': 'account', 'mode': 'list'});
// accounts2 = accounts variable
var accounts2 = xService;
...
Ít đến bữa tiệc. Nhưng tôi nghĩ rằng điều này hữu ích hơn cho những ai muốn tìm hiểu (hoặc có sự rõ ràng) về việc phát triển Dịch vụ tùy chỉnh Angular JS bằng cách sử dụng các phương pháp của nhà máy, dịch vụ và nhà cung cấp.
Tôi đã xem qua video này giải thích rõ ràng về các phương pháp của nhà máy, dịch vụ và nhà cung cấp để phát triển Dịch vụ tùy chỉnh AngularJS:
https://www.youtube.com/watch?v=oUXku28ex-M
Mã nguồn: http://www.techcbt.com/Post3533/Angular-JS-basics/how-to-develop-angularjs-custom-service
Mã được đăng ở đây được sao chép trực tiếp từ nguồn trên, để mang lại lợi ích cho độc giả.
Mã cho dịch vụ tùy chỉnh dựa trên "nhà máy" như sau (đi kèm với cả phiên bản đồng bộ hóa và không đồng bộ cùng với gọi dịch vụ http):
var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcFactory',
function($scope, calcFactory) {
$scope.a = 10;
$scope.b = 20;
$scope.doSum = function() {
//$scope.sum = calcFactory.getSum($scope.a, $scope.b); //synchronous
calcFactory.getSum($scope.a, $scope.b, function(r) { //aynchronous
$scope.sum = r;
});
};
}
]);
app.factory('calcFactory', ['$http', '$log',
function($http, $log) {
$log.log("instantiating calcFactory..");
var oCalcService = {};
//oCalcService.getSum = function(a,b){
// return parseInt(a) + parseInt(b);
//};
//oCalcService.getSum = function(a, b, cb){
// var s = parseInt(a) + parseInt(b);
// cb(s);
//};
oCalcService.getSum = function(a, b, cb) { //using http service
$http({
url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
method: 'GET'
}).then(function(resp) {
$log.log(resp.data);
cb(resp.data);
}, function(resp) {
$log.error("ERROR occurred");
});
};
return oCalcService;
}
]);
Mã cho phương pháp "dịch vụ" cho Dịch vụ tùy chỉnh (điều này khá giống với 'nhà máy', nhưng khác với quan điểm cú pháp):
var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
$scope.a = 10;
$scope.b = 20;
$scope.doSum = function(){
//$scope.sum = calcService.getSum($scope.a, $scope.b);
calcService.getSum($scope.a, $scope.b, function(r){
$scope.sum = r;
});
};
}]);
app.service('calcService', ['$http', '$log', function($http, $log){
$log.log("instantiating calcService..");
//this.getSum = function(a,b){
// return parseInt(a) + parseInt(b);
//};
//this.getSum = function(a, b, cb){
// var s = parseInt(a) + parseInt(b);
// cb(s);
//};
this.getSum = function(a, b, cb){
$http({
url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
method: 'GET'
}).then(function(resp){
$log.log(resp.data);
cb(resp.data);
},function(resp){
$log.error("ERROR occurred");
});
};
}]);
Mã cho phương pháp "nhà cung cấp" cho Dịch vụ tùy chỉnh (điều này là cần thiết, nếu bạn muốn phát triển dịch vụ có thể được định cấu hình):
var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
$scope.a = 10;
$scope.b = 20;
$scope.doSum = function(){
//$scope.sum = calcService.getSum($scope.a, $scope.b);
calcService.getSum($scope.a, $scope.b, function(r){
$scope.sum = r;
});
};
}]);
app.provider('calcService', function(){
var baseUrl = '';
this.config = function(url){
baseUrl = url;
};
this.$get = ['$log', '$http', function($log, $http){
$log.log("instantiating calcService...")
var oCalcService = {};
//oCalcService.getSum = function(a,b){
// return parseInt(a) + parseInt(b);
//};
//oCalcService.getSum = function(a, b, cb){
// var s = parseInt(a) + parseInt(b);
// cb(s);
//};
oCalcService.getSum = function(a, b, cb){
$http({
url: baseUrl + '/Sum?a=' + a + '&b=' + b,
method: 'GET'
}).then(function(resp){
$log.log(resp.data);
cb(resp.data);
},function(resp){
$log.error("ERROR occurred");
});
};
return oCalcService;
}];
});
app.config(['calcServiceProvider', function(calcServiceProvider){
calcServiceProvider.config("http://localhost:4467");
}]);
Cuối cùng, UI hoạt động với bất kỳ dịch vụ nào ở trên:
<html>
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js" ></script>
<script type="text/javascript" src="t03.js"></script>
</head>
<body ng-app="app">
<div ng-controller="emp">
<div>
Value of a is {{a}},
but you can change
<input type=text ng-model="a" /> <br>
Value of b is {{b}},
but you can change
<input type=text ng-model="b" /> <br>
</div>
Sum = {{sum}}<br>
<button ng-click="doSum()">Calculate</button>
</div>
</body>
</html>
Chỉ cần làm rõ mọi thứ, từ nguồn AngularJS, bạn có thể thấy một dịch vụ chỉ cần gọi chức năng của nhà máy mà lần lượt gọi chức năng của nhà cung cấp:
function factory(name, factoryFn) {
return provider(name, { $get: factoryFn });
}
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
Chúng ta hãy thảo luận về ba cách xử lý logic kinh doanh trong AngularJS một cách đơn giản: ( Lấy cảm hứng từ khóa học Coursera AngularJS của Yaakov )
DỊCH VỤ :
Cú pháp:
app.js
var app = angular.module('ServiceExample',[]);
var serviceExampleController =
app.controller('ServiceExampleController', ServiceExampleController);
var serviceExample = app.service('NameOfTheService', NameOfTheService);
ServiceExampleController.$inject = ['NameOfTheService'] //protects from minification of js files
function ServiceExampleController(NameOfTheService){
serviceExampleController = this;
serviceExampleController.data = NameOfTheService.getSomeData();
}
function NameOfTheService(){
nameOfTheService = this;
nameOfTheService.data = "Some Data";
nameOfTheService.getSomeData = function(){
return nameOfTheService.data;
}
}
index.html
<div ng-controller = "ServiceExampleController as serviceExample">
{{serviceExample.data}}
</div>
Các tính năng của dịch vụ:
NHÀ MÁY
Trước tiên, hãy xem cú pháp:
app.js :
var app = angular.module('FactoryExample',[]);
var factoryController = app.controller('FactoryController', FactoryController);
var factoryExampleOne = app.factory('NameOfTheFactoryOne', NameOfTheFactoryOne);
var factoryExampleTwo = app.factory('NameOfTheFactoryTwo', NameOfTheFactoryTwo);
//first implementation where it returns a function
function NameOfTheFactoryOne(){
var factory = function(){
return new SomeService();
}
return factory;
}
//second implementation where an object literal would be returned
function NameOfTheFactoryTwo(){
var factory = {
getSomeService : function(){
return new SomeService();
}
};
return factory;
}
Bây giờ sử dụng hai ở trên trong bộ điều khiển:
var factoryOne = NameOfTheFactoryOne() //since it returns a function
factoryOne.someMethod();
var factoryTwo = NameOfTheFactoryTwo.getSomeService(); //accessing the object
factoryTwo.someMethod();
Đặc điểm của Nhà máy:
.service()
phương pháp là một nhà máy mà luôn tạo ra cùng một loại dịch vụ, mà là một singleton, và không có cách nào dễ dàng để cấu hình hành vi của nó. .service()
Phương pháp đó thường được sử dụng như một lối tắt cho một cái gì đó không yêu cầu bất kỳ cấu hình nào.CÁC NHÀ CUNG CẤP
Trước tiên chúng ta hãy xem Cú pháp trước:
angular.module('ProviderModule', [])
.controller('ProviderModuleController', ProviderModuleController)
.provider('ServiceProvider', ServiceProvider)
.config(Config); //optional
Config.$inject = ['ServiceProvider'];
function Config(ServiceProvider) {
ServiceProvider.defaults.maxItems = 10; //some default value
}
ProviderModuleController.$inject = ['ServiceProvider'];
function ProviderModuleController(ServiceProvider) {
//some methods
}
function ServiceProvider() {
var provider = this;
provider.defaults = {
maxItems: 10
};
provider.$get = function () {
var someList = new someListService(provider.defaults.maxItems);
return someList;
};
}
}
Các tính năng của Nhà cung cấp:
.service
hoặc.factory
phương pháp.$get
là một chức năng được gắn trực tiếp với thể hiện của nhà cung cấp. Chức năng đó là chức năng của nhà máy . Nói cách khác, nó giống như cái mà chúng ta sử dụng để cung cấp cho .factory
phương thức. Trong chức năng đó, chúng tôi tạo ra dịch vụ riêng của chúng tôi. Đây $get
bất động sản, đó là một chức năng, là những gì làm cho các nhà cung cấp một nhà cung cấp . AngularJS hy vọng nhà cung cấp sẽ có một tài sản $ get có giá trị là một chức năng mà Angular sẽ coi là một chức năng của nhà máy. Nhưng điều làm cho toàn bộ nhà cung cấp này thiết lập rất đặc biệt, đó là thực tế là chúng tôi có thể cung cấp một số config
đối tượng bên trong nhà cung cấp dịch vụ và thường đi kèm với các mặc định mà sau này chúng tôi có thể ghi đè lên trong bước, nơi chúng tôi có thể định cấu hình toàn bộ ứng dụng.Nhà máy: Nhà máy bạn thực sự tạo ra một đối tượng bên trong nhà máy và trả lại.
dịch vụ: Dịch vụ bạn chỉ có một chức năng tiêu chuẩn sử dụng từ khóa này để xác định chức năng.
nhà cung cấp: Nhà cung cấp có $ giúp bạn xác định và nó có thể được sử dụng để lấy đối tượng trả về dữ liệu.
Về cơ bản, Nhà cung cấp, Nhà máy và Dịch vụ đều là Dịch vụ. Nhà máy là trường hợp đặc biệt của Dịch vụ khi tất cả những gì bạn cần là hàm $ get (), cho phép bạn viết nó với ít mã hơn.
Sự khác biệt chính giữa Dịch vụ, Nhà máy và Nhà cung cấp là sự phức tạp của chúng. Dịch vụ là hình thức đơn giản nhất, Các nhà máy mạnh hơn một chút và Nhà cung cấp có thể định cấu hình khi chạy.
Dưới đây là tóm tắt về thời điểm sử dụng từng:
Nhà máy : Giá trị bạn đang cung cấp cần được tính toán dựa trên dữ liệu khác.
Dịch vụ : Bạn đang trả về một đối tượng với các phương thức.
Nhà cung cấp : Bạn muốn có thể định cấu hình, trong giai đoạn cấu hình, đối tượng sẽ được tạo trước khi nó được tạo. Sử dụng Nhà cung cấp chủ yếu trong cấu hình ứng dụng, trước khi ứng dụng được khởi tạo hoàn toàn.
1. Dịch vụ là các đối tượng đơn lẻ được tạo khi cần thiết và không bao giờ được dọn sạch cho đến khi kết thúc vòng đời ứng dụng (khi đóng trình duyệt). Bộ điều khiển bị phá hủy và dọn dẹp khi không còn cần thiết.
2. Cách dễ nhất để tạo một dịch vụ là sử dụng phương thức Factory (). Phương thức Factory () cho phép chúng ta xác định một dịch vụ bằng cách trả về một đối tượng có chứa các hàm dịch vụ và dữ liệu dịch vụ. Hàm định nghĩa dịch vụ là nơi chúng tôi đặt các dịch vụ có thể tiêm của mình, chẳng hạn như $ http và $ q. Ví dụ:
angular.module('myApp.services')
.factory('User', function($http) { // injectables go here
var backendUrl = "http://localhost:3000"; var service = {
// our factory definition
user: {},
setName: function(newName) {
service.user['name'] = newName;
},
setEmail: function(newEmail) { service.user['email'] = newEmail;
},
save: function() {
return $http.post(backendUrl + '/users', { user: service.user
}); }
};
return service; });
Sử dụng nhà máy () trong ứng dụng của chúng tôi
Thật dễ dàng để sử dụng nhà máy trong ứng dụng của chúng tôi vì chúng tôi có thể chỉ cần đưa nó vào nơi chúng tôi cần vào thời gian chạy.
angular.module('myApp')
.controller('MainController', function($scope, User) {
$scope.saveUser = User.save;
});
Đường tổng hợp là sự khác biệt . Chỉ có nhà cung cấp là cần thiết. Hay nói cách khác, chỉ có nhà cung cấp là góc cạnh thực sự, tất cả những người khác đều có nguồn gốc (để giảm mã). Cũng có một phiên bản đơn giản, được gọi là Value () chỉ trả về giá trị, không tính toán hoặc hàm. Ngay cả Giá trị có nguồn gốc từ nhà cung cấp!
Vậy tại sao lại phức tạp như vậy, tại sao chúng ta không thể sử dụng nhà cung cấp và quên mọi thứ khác? Nó được cho là giúp chúng ta viết mã dễ dàng và giao tiếp tốt hơn. Và câu trả lời trực tiếp sẽ là, càng phức tạp thì càng bán được một khung tốt hơn.
Tiêm góc cho chúng ta gợi ý đầu tiên để đi đến kết luận này.
"$ Kim phun được sử dụng để truy xuất các thể hiện đối tượng như được xác định bởi nhà cung cấp " không phải dịch vụ, không phải nhà máy mà là nhà cung cấp.
Và một câu trả lời tốt hơn sẽ là: "Một dịch vụ Angular được tạo ra bởi một nhà máy dịch vụ. Các nhà máy dịch vụ này là các chức năng, do đó, được tạo ra bởi một nhà cung cấp dịch vụ. Các nhà cung cấp dịch vụ là các hàm xây dựng. được gọi là $ get, giữ chức năng nhà máy dịch vụ. "
Vì vậy, nhà cung cấp chính và người tiêm và tất cả sẽ rơi vào vị trí :). Và nó trở nên thú vị trong Typecript khi $ get có thể được triển khai trong một nhà cung cấp bằng cách kế thừa từ IServiceProvider.