虽然Anguar提供了一些常用的services,但对于一个普通的程序来说,你会需要创建自己的Services。通常在一个module的service factory函数中通过Module#factory
api注册一个service,或者直接在module的config
函数中使用$provide
api注册。
所有的Anguar services都使用一个唯一的name(id)注册到Anguar的依赖注入(DI)系统当中,同时它也可以声明它自己依赖的、需要提供给其工厂函数的其他service。services拥有可被替换的能力,所以在测试中可将services替换为mocks/stubs/dummies,这让services高度可测。
为了注册一个service,你必须让它属于某一个module。然后,你可以通过Module
api或在module的配置函数中使用$provide
service来注册该service。下面的伪代码展示了这两种方式:
使用angular.Module
api:
var myModule = angular.module('myModule', []);
myModule.factory('serviceId', function() {
var shinyNewServiceInstance;
//factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});
使用$provide service:
angular.module('myModule', [], function($provide) {
$provide.factory('serviceId', function() {
var shinyNewServiceInstance;
//factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});
});
注意,你注册的不是一个service实例,而是一个工厂函数,它将在被调用时生成一个实例。
Services不光可被依赖,它自己也可以有自己的依赖。这些依赖可在工厂函数中以参数的方式来指定。关于Angular的DI,以及如何在压缩js代码时使用数组和$inject属性来处理依赖的声明,参见这里。TODO
下面是一个简单service的例子。这个service依赖于$window
service(它将以参数方式传给工厂方法),它仅仅是一个函数。这个函数简单地保存了所有的通知,并收到第三个之后,它会把所有的通知由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 = [];
}
};
}]);
});
Angular中所有的services都是延迟初始化,这表明只有当一个service被程序组件依赖或初始化另一个service时,它才会被创建。换言之,Angular只有当一个service被直接或间接请求时,才会初始化它。
最后,需要着重注意的是,所有的angular services都是程序级的单例对象。这表明对于每一个injector,每个service只有一个实例。由于Angular非常不喜欢全局状态,所以可以使用多个injector,每个都有自己单独的service实例。这种需求很少见,除非是在测试中(这个功能对于测试来说很重要)。
ng