2014年7月23日 星期三

AngularJS 教學 - provider method

在前兩篇
AngularJS 教學 - factory method
AngularJS 教學 - service method

介紹到了三種建立 service 的其中兩個方法,factory 與 service

最後就要來介紹第三種方法,provider

provider 方法是 AngularJS Module 所提供的一個建立 Service 的方法 (Module.provider)

provider 方法與其他兩個最大的不同在於它能夠對 Service Object 做額外的設定(Configured)

再談到如何做額外的設定之前,我們先來看一個基本的 provider 方法如何使用

var demoApp = angular.module("demoApp", []);
demoApp.provider("echoService", function(){
return {  //It's Provider Object
$get: function(){
            return {  //It's Service Object
               echoCount: 0,
               echo: function(name){
                   console.log((this.echoCount++) + ", Your name is " + name);
               }
            };
        }
}

});



再使用 provider 方法的時候,同樣要給兩個參數

分別是 service 的名稱以及一個能夠回傳 Provider Object 的工廠方法

這也是 provider 與其他兩個的差別之一

你所提供的工廠方法並不是像 factory 方法是直接回傳一個 Service Object

而是一個 Provider Object,而這個 Provider Object 必須包含一個 $get的函式

而 $get函式才需要回傳真正的 Service Object

從需求角度來看,當你的 Service 被請求時

AngularJS 會呼叫你的工廠方法以得到一個 Provider Object

再呼叫 Provider Object 的 $get函式才會得到真正的 Service Object

但我們會使用 provider 方法的目的不僅在於建立一個 Service Object

重點在於前面所說的,使用 provider 方法能夠讓我們增加額外的函式來設定 Service Object

接下來的範例我提供了一個設定的功能來設定 Service Object 的 echo 函式是否能夠正常work

demoApp.provider("echoService", function(){
    var enableEcho = true;
        return {  //It's Provider Object
            echoFunctionEnabled: function(enabled){
                enableEcho = enabled;
            },
            $get: function(){
                return {  //It's Service Object
                    echoCount: 0,
                    echo: function(name){
                        if(enableEcho){
                            console.log((this.echoCount++) + ", Your name is " + name);
                        }else {
                            console.log("Echo function disabled.");
                        }
                }
            };
        }
    }

});

我在 Provider Object 增加一個 echoFunctionEnabled 的函式,傳入一個布林值來設定 enableEcho 變數

當 enableEcho 是 false 時,就不 log 出訊息,改為 log  "Echo function disabled"

至於我們該如何在適當時機點呼叫 Provider Object 的 echoFunctionEnabled 函式呢?

demoApp.config(function (echoServiceProvider) {
    echoServiceProvider.echoFunctionEnabled(false);

});

我們可以透過 (Module.config) 來進行設定,config 會在 AngularJS 把所有的模組載入之後

才會執行,上面的範例可以看到,我們必須用 Service 名稱加上 "Provider"

才能取到該 Service 的 Provider Object,取到 Provider Object 之後,就可以進行設定的動作了

底下是完整的程式範例

<html xmlns="http://www.w3.org/1999/xhtml" ng-app="demoApp">
     <head>
         <title>Examples</title>
         <script type="text/javascript" src="js/angular.min.js"></script>
         <script>
              var demoApp = angular.module("demoApp", []);
              demoApp.provider("echoService", function(){
               var enableEcho = true;
               return {
                    echoFunctionEnabled: function(enabled){
                        enableEcho = enabled;
                    },
                    $get: function(){
                        return {
                            echoCount: 0,
                            echo: function(name){
                                 if(enableEcho){
                                      console.log((this.echoCount++) + ", Your name is " + name);
                                 }else {
                                      console.log("Echo Function disabled.");
                                 }
                             }
                          };
                    }
               }
             });
              demoApp.config(function (echoServiceProvider) {
                  echoServiceProvider.echoFunctionEnabled(false);
              });
              demoApp.controller("demoCtrl", function($scope, echoService){
                  $scope.name = "Allen";
                  $scope.echo = function(){
                       echoService.echo($scope.name);
                  };
             });
         </script>
     </head> 
     <body>
         <div ng-controller="demoCtrl">
              Name : <input type="text" ng-model="name"/><br/>
              <button ng-click="echo()">click</button>
         </div>
     </body>

</html>

需要注意的是 Module.config 的問題,剛剛有提到 confgi 會在 AngularJS 載入完所有的模組之後才會被執行

因此如果上述範例我如果把 config 換到 provider 之前,就會發生錯誤了

demoApp.config(function (echoServiceProvider) {........
demoApp.provider("echoService",......

原因就是因為 config 被執行時,provider 都還沒被定義

當然這在比較大型專案中,可能會覺得很奇怪

原因是因為我的範例為了方便並沒有分劃出模組,

如果在真實的專案中有把模組規劃清楚,則可以透過模組間的依賴關係

就不會發生類似的問題了,如果不清楚模組的內容可以看 AngularJS 教學 - Module

沒有留言:

張貼留言