AngularJS給我們提供了很多內(nèi)置的服務(wù)泌射,比如 $http, $log 等燥爷,我們也可以自定義服務(wù)妈踊,有幾種方式自定義服務(wù):factory
, service
, provider
一.什么是Service
服務(wù)的特點(diǎn)是什么:
- 最終目的就是可重用性
- 一個(gè)能在不同控制器中使用的特別的代碼單元
- 服務(wù)可以當(dāng)作工具或者業(yè)務(wù)邏輯單元
-
服務(wù)是
單例
,只被實(shí)例化一次矾削,然后一直保存在Angular應(yīng)用中碗殷。而controllers則是需要使用時(shí)被構(gòu)造肩刃,不需要時(shí)被銷毀 - 只有一個(gè)控制器注入服務(wù)時(shí)祟霍,服務(wù)才被實(shí)例化,懶加載
- 控制器可以同時(shí)使用多個(gè)服務(wù)
-
一個(gè)服務(wù)也可以注入其它服務(wù)
#1service.jpg
二.創(chuàng)建自定義服務(wù)
創(chuàng)建服務(wù)有3中方式盈包, factory
, service
, provider
:
- 其中
factory
,service
只是寫法上有些微差異沸呐,下面會(huì)詳細(xì)介紹語(yǔ)法 -
factory
,service
其實(shí)是provider
的語(yǔ)法糖 -
provider
可以在服務(wù)實(shí)例化之前提供一些配置參數(shù)(配置階段
),在配置階段不能使用服務(wù)续语,這點(diǎn)需要注意 -
provider
必須返回一個(gè)this.$get
函數(shù)垂谢,這個(gè)函數(shù)就相當(dāng)于factory
下面具體來(lái)看這3種方式的語(yǔ)法
1.Factory
語(yǔ)法:
app.factory(factoryName, [DI, function(DI) { // 注入其它的服務(wù)
// 定義一個(gè)對(duì)象
var oService = {};
// 定義對(duì)象上的屬性方法
oService.getSum = function() {}
...
// 將這個(gè)對(duì)象返回
return oService
}])
示例:
// html
<div ng-controller="sample">
a: {{a}} <input ng-model="a" /> <br/>
b: {} <input ng-model="b" /> <br/>
sum = {{sum}}
<button ng-click="getSum()">總和</button>
</div>
// js
app.controller('sample', ['calcFactory', function(calcFactory) { // 使用該服務(wù)
$scope.a = 0;
$scope.b = 0;
$scope.sum = 0;
$scope.getSum = function() {
$scope.sum = calcFactory.addSum($scope.a, $scope.b); // 調(diào)用factory上的方法
}
}])
// 定義factory
app.factory('calcFactory', ['$log', function($log) {
var oCalcService = {}; // 定義一個(gè)對(duì)象
// 對(duì)象上的屬性方法 同步方法
oCalcService.addSum = function(a, b) {
return parseInt(a, 10) + parseInt(b, 10);
}
// 其它的一些方法屬性
// 返回該對(duì)象
return oCalcService;
}])
上面我們?cè)诜?wù)中定義的方法使用的是同步方法疮茄,我們可以使用異步的方式來(lái)處理滥朱,這種方式也比較常見(jiàn)
// js
app.controller('sample', ['calcFactory', function(calcFactory) { // 使用該服務(wù)
$scope.a = 0;
$scope.b = 0;
$scope.sum = 0;
$scope.getSum = function() {
calcFactory.addSum($scope.a, $scope.b, function(r) {
$scope.sum = r; // 這里簡(jiǎn)單的將結(jié)果賦給$scope.sum
}); // 第3個(gè)參數(shù)為回調(diào)函數(shù),可以自定義邏輯
}
}])
// 定義factory
app.factory('calcFactory', ['$log', function($log) {
var oCalcService = {};
// 對(duì)象上的屬性方法 異步方法
// 第3個(gè)參數(shù)為一個(gè)回調(diào)函數(shù)力试,邏輯由控制器決定
oCalcService.addSum = function(a, b, cb) {
var r = parseInt(a, 10) + parseInt(b, 10);
cb(r);
}
return oCalcService;
}])
另外假設(shè)我們的計(jì)算過(guò)程是在服務(wù)端完成的徙邻,這時(shí)我們需要使用 $http
服務(wù)
// 定義factory
app.factory('calcFactory', ['$log', '$http', function($log, $http) { // 使用'$http'服務(wù)
var oCalcService = {};
oCalcService.addSum = function(a, b, cb) {
// 在服務(wù)端計(jì)算
// 假設(shè)服務(wù)端地址為'http://localhost:8888/Sum?a=10&b=20'(10, 20)為傳入的參數(shù)
$http({
url: 'http://localhost:8888/Sum?a=' + a + '&b=' + b,
method: 'GET'
}, function(res) {
cb(res.data); // 獲取結(jié)果,傳給回調(diào)函數(shù)
}, function(err) {
$log.log(err); // 錯(cuò)誤處理
})
}
return oCalcService;
}])
2.Service
這個(gè)和Factory并沒(méi)有什么差異畸裳,只是寫法的不同缰犁,它會(huì)跟一個(gè)構(gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)會(huì)被AngularJS 自動(dòng)
實(shí)例化
語(yǔ)法:
// 后面是構(gòu)造函數(shù),可以直接使用'this'
// 服務(wù)被調(diào)用時(shí)帅容,Angular將自動(dòng)的實(shí)例化這個(gè)構(gòu)造器
app.service(serviceName, [DI, function(DI) {
this.addSum = function() {};
this.timeSUm = function();
// 其余邏輯
}])
示例(使用上面的例子):
app.controller('sample', ['calcService', function(calcService) { // 使用該服務(wù)
$scope.a = 0;
$scope.b = 0;
$scope.sum = 0;
$scope.getSum = function() {
$scope.sum = calcService.addSum($scope.a, $scope.b, function(r) {
$scope.sum = r;
}); // 調(diào)用calcService上的方法
}
}])
app.service('calcService', ['$log', function($log) {
this.addSum = function(a, b, cb) {
var s = parseInt(a) + parseInt(b);
cb(s);
}
}])
可以看出幾乎和Factory的寫法一致
3.Provider
這個(gè)寫法和上面的有很大的差異颇象,因?yàn)樗梢蕴砑?配置
, 這些配置參數(shù)可以在配置階段使用,使用時(shí)需要注意的是并徘,注入的服務(wù)需要添加在 this.$get
函數(shù)中遣钳,不能直接添加在provider函數(shù)中,因?yàn)榕渲秒A段注入服務(wù)是訪問(wèn)不到的
語(yǔ)法:
app.provider(providerName, function() {
// 配置函數(shù)麦乞, 'config' 可以是別的變量名, 比如'this.settings'
// 下面的 'providerNameProvider.config(params)'會(huì)使用到
// 在服務(wù)被實(shí)例化之前被 'Provider' 執(zhí)行
this.config = function(params) {}
// 實(shí)質(zhì)是一個(gè)Factory
// 可以使用provider提供的配置信息
this.$get = [DI, function(DI) {
var someObj = {};
someObj.someMethod = function() {};
return someObj;
}]
})
// 給服務(wù)提供配置
// 在服務(wù)實(shí)例化之前提供配置信息
// 在配置階段被執(zhí)行
// 注意名字只能是服務(wù)名后面添加'Provider'
app.config[providerNameProvider, function(providerNameProvider) {
providerNameProvider.config(params)
}]
示例, 假如我們上面服務(wù)端計(jì)算的url可以自己配置:
app.provider('calcService', function() {
var baseUrl = '';
this.settings = function(url) {
baseUrl = url;
}
this.$get = ['$log', '$http', function($log, $http) {
var oCalcObject = {};
oCalcObject.addSum = function(a, b, cb) {
$http({
url: baseUrl + '/Sum?a=' + a + '&b=' + b,
method: 'GET'
}).then(function(res) {
$log(res.data);
cb(res.data)
}, function(err) {
$log.log(err);
})
}
}]
})
// 配置
app.config('calcServiceProvider', function(calcServiceProvider) {
calcServiceProvider.settings('http://localhost: 8888')
})
可以看出provider和其它2種方式最大的不同就是蕴茴,可以提供配置信息,這樣寫可以更靈活姐直,不必寫死倦淀。