服務是AngularJS中非常重要的一個概念,雖然我們有了控制器,但考慮到其生命實在脆弱,我們需要用到服務。
起初用service時,我便把service和factory()理所當然地關聯起來了。
確實,factory()是創建一個服務的最簡單的方式,但服務並非僅此而已。
這裡記錄一下我對服務的一些簡單認識。
Service
非常重要的一點 —— 服務是單例。
一個服務在一個AngularJS應用中只會被$injector實例化一次,並貫穿應用的整個生命周期,與脆弱的控制器們進行通信。
先從注冊一個服務開始,注冊服務的最常見方式便是factory()。
比如:
var myApp = angular.module('myApp',[])
.factory('myService',function() {
return {};
});
factory()以對象或者函數形式返回一個服務。
我們試試給myService注入$http服務,寫一個像那麼回事的東西。
(ps:找了一些URL都不是很理想,我也只好學別人的demo,從github獲取用戶的活動日志信息)
注入? 把服務注入給控制器也是這樣,把服務的名字放到參數列表裡就算是注入了,但這只是簡單的方式。
好了,先把myService修改一下:
.factory('myService',function($http) {
return {
getUserActivities: function(username){
return $http({
method: 'JSONP',
url:'https://api.github.com/users/'+username+'/events?callback=JSON_CALLBACK'
});
}
};
})
根據輸入的用戶名進行請求,輸出活動信息,視圖如下:
<div ng-controller="myController">
<input type="text" ng-model="username" />
<table border="1">
<tr>
<th></th>
<th>user</th>
<th>to</th>
<th>at</th>
</tr>
<tr ng-repeat="activity in activities">
<td><img src="{{activity.actor.avatar_url}}" width="25px" height="25px"/></td>
<td>{{ activity.actor.login }} </td>
<td>{{ activity.repo.name }}</td>
<td>{{activity.created_at}}</td>
</tr>
</table>
</div>
我們需要$watch這個變量,但需要注意的是,如果請求頻率超過限制,github會給個403。
因此還需要用$timeout控制一下請求頻率,一段時間之內重復請求就把之前的干掉。
控制器調用服務代碼如下:
.controller('myController',function($scope,myService,$timeout,$log){
var timeout;
$scope.$watch('username',function(){
if(timeout){
$timeout.cancel(timeout)
$log.info('timeout:::'+timeout);
}
timeout= $timeout(function(){
myService.getUserActivities($scope.username)
.success(function(response, status, headers, config){
$scope.activities = response.data;
})
.error(function(response, status, headers, config){
$log.info(status)
})},1000);
});
})
用factory()注冊一個服務似乎不那麼復雜。
事實上,我們有5種方式來創建服務:
•factory
•service
•constant
•value
•provider
factory
最簡單的方式,該函數接收2個參數
•name (string):服務名
•getFn (function/array):AngularJS實例化服務時調用該函數
service
可能是因為更加語義化的緣故,比起factory(),我更喜歡service()。
service也同樣接收2個參數,分別是:
•name (string):服務名
•constructor (function):服務對象的構造函數
試著改用service():
.service('myService',function($http) {
this.getUserActivities = function(username){
return $http({
method: 'JSONP',
url:'https://api.github.com/users/'+username+'/events?callback=JSON_CALLBACK'
});
}
})
constant與value
這兩個名字感覺比較另類,它們的參數都是一樣的:
•name
•value
僅從語義上來講,如果服務的$get方法只是返回個常量,這兩個方法確實適合。
可能會嘗試寫個函數進去,如果只是定義的話則不會報錯。
但不會有相應的provider,調用時也會提示該服務不是一個函數之類的問題。
所以還是老老實實地這樣使用:
.constant('serviceId','00001')
那兩者的區別又是什麼?
區別在於注入到config()時,以上面的serviceId為例。
如果serviceId是個constant,我們可以將serviceId注入到config()中,但是無法將serviceIdProvider注入到config()中,而value則剛好相反。
provider
provider()是最原始的方法。
我們試著用factory()和provider()創建相同的服務進行對比。
.factory('aService',{
'name':'a'
})
.provider('bService',{
$get: {'name':'b'}
})
也就是說factory()的第二個參數相當於是$get?
provider()接收兩個參數:
•name (string) :仍然是服務實例的名字,如果name+'Provider'便是provider的名字。
•provider (object/array/function) : 不是服務,是帶$get()的provider
$provide服務在運行時初始化provider,$injector調用$get創建服務實例。
那為什麼要用provider()而不是其他方式? 關鍵在於config(),如果我們給多個應用共享某個服務,但在注入服務之前給注入到不同應用的服務進行相應的設置,則需要在config()中通過服務的provider進行設置,比如加個decorator什麼的。
decorator
就是裝飾服務,添加功能或者完全改變服務。
decorator()接收兩個參數
•name (string):要裝飾的服務的名稱
•decoratorFn (function):服務實例化時由$injector調用該函數。
下面是一個例子,在獲得用戶活動信息後輸出耗時:
.config(function(myServiceProvider,$provide){
$provide.decorator('myService',function($delegate,$log) {
var activities = function(username) {
var startedAt = new Date();
var activities = $delegate.getUserActivities(username);
activities.finally(function() {
$log.info("Fetching activities" +" took " +(new Date() - startedAt) + "ms");
});
return activities;
};
return {getUserActivities:activities};
});
})
一些AngularJS相關文章鏈接:
AngularJS權威教程 清晰PDF版 http://www.linuxidc.com/Linux/2015-01/111429.htm
希望你喜歡,並分享我的工作~帶你走近AngularJS系列:
如何在 AngularJS 中對控制器進行單元測試 http://www.linuxidc.com/Linux/2013-12/94166.htm
在 AngularJS 應用中通過 JSON 文件來設置狀態 http://www.linuxidc.com/Linux/2014-07/104083.htm
AngularJS 之 Factory vs Service vs Provider http://www.linuxidc.com/Linux/2014-05/101475.htm
AngularJS —— 使用 ngResource、RESTful APIs 和 Spring MVC 框架提交數據 http://www.linuxidc.com/Linux/2014-07/104402.htm
AngularJS 的詳細介紹:請點這裡
AngularJS 的下載地址:請點這裡