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ụ , Angular 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;
}
});
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.
- baseUrl là URL cơ sở mà API iTunes yêu cầu
- _artist là nghệ sĩ chúng tôi muốn tìm kiếm
- _finalUrl là URL cuối cùng và được xây dựng đầy đủ để chúng tôi thực hiện cuộc gọi tới iTunes makeUrl là một chức năng sẽ tạo và trả lại URL thân thiện với iTunes của chúng tôi.
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ụ', chúng tôi sẽ có thể sử dụng trực tiếp 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 Angular, 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ả về cuộc gọi nghệ sĩ. Các cuộc gọi đầu tiên 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 các thuộc tính trên đối tượng $ scope xuất phát từ 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". 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 line below this creates an obj object 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 Angular 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 ở Angular.