走進AngularJs(六) 服務

呂大豹發表於2013-12-08

  今天學習了一下ng的service機制,作為ng的基本知識之一,有必要做一個瞭解,在此做個筆記記錄一下。

一、認識服務(service)

  服務這個概念其實並不陌生,在其他語言中如java便有這樣的概念,其作用就是對外提供某個特定的功能,如訊息服務,檔案壓縮服務等,是一個獨立的模組。ng的服務是這樣定義的:

Angular services are singletons objects or functions that carry out specific tasks common to web apps.

  它是一個單例物件或函式,對外提供特定的功能。

  • 首先是一個單例,即無論這個服務被注入到任何地方,物件始終只有一個例項。
  • 其次這與我們自己定義一個function然後在其他地方呼叫不同,因為服務被定義在一個模組中,所以其使用範圍是可以被我們管理的。ng的避免全域性變數汙染意識非常強。

  ng提供了很多內建的服務,可以到API中檢視http://docs.angularjs.org/api/。知道了概念,我們來拉一個service出來溜溜,看看到底是個什麼用法。(從這篇文章開始,我就使用jsfiddle來寫示例程式碼了,再也不折騰部落格園的變態編輯器了~)  

  我們在controller中直接宣告$location服務,這依靠ng的依賴注入機制。$location提供位址列相關的服務,我們在此只是簡單的獲取當前的地址。

  服務的使用是如此簡單,我們可以把服務注入到controller、指令或者是其他服務中。

二、自定義服務

  如同指令一樣,系統內建的服務以$開頭,我們也可以自己定義一個服務。定義服務的方式有如下幾種:

  • 使用系統內建的$provide服務
  • 使用Module的factory方法
  • 使用Module的service方法

  下面通過一個小例子來分別試驗一下。我們定義一個名為remoteData服務,它可以從遠端獲取資料,這也是我們在程式中經常使用的功能。不過我這裡沒有遠端伺服器,就寫死一點資料模擬一下。

//使用$provide來定義
var app = angular.module('MyApp', [], function($provide) {
    $provide.factory('remoteData', function() {
        var data = {name:'n',value:'v'};
        return data;
    });
});
//使用factory方法
app.factory('remoteData',function(){
    var data = {name:'n',value:'v'};
    return data;
});
//使用service方法
app.service('remoteData',function(){
    this.name = 'n';
    this.value = 'v';
});

  Module的factory和$provide的factory方法是一模一樣的,從官網文件看它們其實就是一回事。至於Module內部是如何呼叫的,我此處並不打算深究,我只要知道怎麼用就好了。

  再看Module的service方法,它沒有return任何東西,是因為service方法本身返回一個構造器,系統會自動使用new關鍵字來建立出一個物件。所以我們看到在構造器函式內可以使用this,這樣呼叫該服務的地方便可以直接通過remoteData.name來訪問資料了。

  下面我們來用一下自己定義好的服務:

三、管理服務的依賴關係

  服務與服務中間可以有依賴關係,例如我們這裡定義一個名為validate的服務,它的作用是驗證資料是否合法,它需要依賴我們從遠端獲取資料的服務remoteData。程式碼如下:

   在factory的引數中,我們可以直接傳入服務remoteData,ng的依賴注入機制便幫我們做好了其他工作。不過一定要保證這個引數的名稱與服務名稱一致,ng是根據名稱來識別的。若引數的名次與服務名稱不一致,你就必須顯示的宣告一下,方式如下:

app.factory('validate',['remoteData',function(remoteDataService){
    return function(){
        if(remoteDataService.name=='n'){
            alert('驗證通過');
        }
    };
}]);

  我們在controller中注入服務也是同樣的道理,使用的名稱需要與服務名稱一致才可以正確注入。否則,你必須使用$inject來手動指定注入的服務。比如:

function testC(scope,rd){
    scope.getData = function(){
        alert('name:'+rd.name+'   value:'+rd.value);
    }
}
testC.$inject = ['$scope','remoteData'];

 -------------------補充於2014.01.11-------------------------

  感謝@Terry Sun指出,在controller中注入服務,也可以在定義controller時使用陣列作為第二個引數,在此處把服務注入進去,這樣在函式體中使用不一致的服務名稱也是可以的,不過要確保注入的順序是一致的,如:

app.controller('testC',['$scope','remoteData',function($scope,rd){
    $scope.getData = function(){
        alert('name:'+rd.name+'   value:'+rd.value);
    }
}]);

 

  ng服務的基本知識也就這些了。目前只是學些皮毛,或許以後用到專案中了才能體會到他的強大之處,以及在真實使用中的這樣那樣的問題。

相關文章