雖然AngularJS提過了很多有用的服務,但是如果你要創(chuàng)建一個很棒的應用,你可能還是要寫自己的服務。你可以通過在模塊中注冊一個服務工場函數,或者通過Modeul#factory api或者直接通過模塊配置函數中的$provide api來實現。
所有的服務都符合依賴注入的原則。它們用一個唯一的名字將自己注冊進AngularJS的依賴注入系統(tǒng)(injector),并且聲明需要提供給工場函數的依賴。它們的依賴在測試中可以是虛擬的,這使得它們能很好地被測試。formatDate
要注冊服務,你首先要有一個包含該服務的模塊。然后你就能通過模塊的api或者使用模塊配置函數中的$provide服務來注冊你的服務了。下面的偽代碼顯示了這兩種方法。
使用angular.Module api:
var myModule = angular.module('myModule', []);myModule.factory('serviceId', function() { var shinyNewServiceInstance; //factory function body that constructs shinyNewServiceInstance return shinyNewServiceInstance;});
使用$provide服務:
angular.module('myModule', [], function($provide) { $provide.factory('serviceId', function() { var shinyNewServiceInstance; //factory function body that constructs shinyNewServiceInstance return shinyNewServiceInstance; });});
注意,你不應該注冊一個服務實例,而是一個會在被調用時創(chuàng)建實例的工場函數。
服務不僅可以被依賴,還可以有自己的依賴。依賴可以在工場函數的參數中指定。參閱AngularJS的依賴注入系統(tǒng),和使用依賴的數組表示法和$inject屬性來讓依賴表示精簡化。
下面是一個很簡單的服務的例子。這個服務依賴于$window服務(會被當成參數傳遞給工場函數),并且只是個函數。這個服務的任務是存儲所有的通知;在第三個通知以后,服務會用window的alert來輸出所有的通知。
angular.module('myModule', [], function($provide) { $provide.factory('notify', ['$window', function(win) { var msgs = []; return function(msg) { msgs.push(msg); if (msgs.length == 3) { win.alert(msgs.join("\n")); msgs = []; } }; }]);});
所有服務都是延遲實例化的。這意味著所有的服務只有在需要時,或者被依賴時才會實例化。換句話說,AngularJS不會實例化服務,除非被要請求了或者被應用直接或間接依賴了。
最好,要注意的是所有AngularJS服務都是單例的。這意味著在每一個注入器中都只有一個需要的服務的實例。因為AngularJS極度討厭全局的東西,所以是可以創(chuàng)建多個注入器的,并且每個住一起有自己的服務實例。但這種情況很少,除非在測試中,這樣的特性才極度重要。