AngularJS - 服務簡介

服務是AngularJS中很是重要的一個概念,雖然咱們有了控制器,但考慮到其生命實在脆弱,咱們須要用到服務。git

起初用service時,我便把servicefactory()理所固然地關聯起來了。
確實,factory()是建立一個服務的最簡單的方式,但服務並不是僅此而已。github

這裏記錄一下我對服務的一些簡單認識。


api

Service

很是重要的一點 —— 服務是單例
一個服務在一個AngularJS應用中只會被$injector實例化一次,並貫穿應用的整個生命週期,與脆弱的控制器們進行通訊。ide


先從註冊一個服務開始,註冊服務的最多見方式即是factory()
好比:函數

var myApp = angular.module('myApp',[])
.factory('myService',function() {
    return {};
});


factory()以對象或者函數形式返回一個服務。
咱們試試給myService注入$http服務,寫一個像那麼回事的東西。this

(ps:找了一些URL都不是很理想,我也只好學別人的demo,從github獲取用戶的活動日誌信息)url

注入? 把服務注入給控制器也是這樣,把服務的名字放到參數列表裏就算是注入了,但這只是簡單的方式。日誌

好了,先把myService修改一下:code

.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};
    });
})
相關文章
相關標籤/搜索