[译]AngularJS Service vs Factory - Once and for all
原文: http://blog.thoughtram.io/angular/2015/07/07/service-vs-factory-once-and-for-all.html
Service和Factory有什么不同,我应该使用哪个?
这篇文章将讲解service和factory的不同之处,为什么我们喜欢service多过于factory.
Service和Factory的不同之处
在AngularJS中service和factory有什么不同? 我们可以这样定义一个service:
1 2 3 4 5 | app.service( 'MyService' , function () { this .sayHello = function () { console.log( 'hello' ); }; }); |
.service()
是我们module的一个方法。 有两个参数,第一个参数是服务名,第二个参数是一个function. 可以把Service注入到其他的component中,如controller, directive, filters. 注入方法如下:
1 2 3 | app.controller( 'AppController' , function (MyService) { MyService.sayHello(); // logs 'hello' }); |
好了,看看factory是如何做同样的事情的:
1 2 3 4 5 6 7 | app.factory( 'MyService' , function () { return { sayHello: function () { console.log( 'hello' ); }; } }); |
.factory()
同样是我们module的一个方法,有两个参数,第一个是factory名,第二个是一个function. 同样factory也可以注入到其他components中. 那么他的不同之处在哪呢?
可以看到在factory中我们没有使用 this
, 而是返回一个对象字面量. 为什么这样?因为,service是一个构造函数factory不是. 所以我们在factory的funtion中要显示的返回一个对象.
来看看AngularJS的源代码中的factory函数是怎样的:
1 2 3 4 5 | function factory(name, factoryFn, enforce) { return provider(name, { $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn }); } |
factory接收一个name, 和factory函数,返回一个同名的provider, $get
是我们的factory函数. 当你获取一个注入,会调用$get()方法向相应的provider请求一个service的实例. 这就是为什么创建provider的时候需要有$get()方法.
换而言之, 当注入MyService
时, 后面究竟发生了什么呢:
1 | MyServiceProvider.$get(); // 返回service的实例 |
现在看看service函数在AngularJS的源代码中是怎么样的:
1 2 3 4 5 | function service(name, constructor) { return factory(name, [ '$injector' , function ($injector) { return $injector.instantiate(constructor); }]); } |
从代码中看得出来,当调用service()的时候实际上最后调用了factory(). 但是没有直接把service的构造函数传给factory. 而是传递了一个依赖injector的函数,通过这个injector去实例化. 简单的说: service调用了预定义的factory, 最后调用相应的provider的$get()方法. $injector.instantiate()
方法最终调用Object.create(),参数为构造函数
. 这就是为什么我们要在service里面使用this.
不论我么使用 service()
还是 factory()
, 最终都是一个factory,然后这个factory去调用provider.
使用哪一个?
“serivce和factory的不同如下:”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | app.service( 'myService' , function () { // service是一个构造函数 this .sayHello = function (name) { return "Hi " + name + "!" ; }; }); app.factory( 'myFactory' , function () { // factory返回一个对象 return { sayHello : function (name) { return "Hi " + name + "!" ; } } }); |
是的service是一个构造函数, 然后我们一样可以在这个构造函数中返回对象字面量. 事实上, 在javascript中构造函数可以返回任何你想返回的东西. 所以我们把service写得和factory一样:
1 2 3 4 5 6 7 8 9 | app.service( 'MyService' , function () { // 我们可以在这加入其它的代码 return { sayHello: function () { console.log( 'hello' ); }; } }); |
现在factory和service的写法已经一样了. 问题是: 我们该使用哪一个呢?
Service能让我们使用ES6的class
在ES6中我们可以这样定义service:
1 2 3 4 5 6 7 | class MyService { sayHello() { console.log( 'hello' ); } } app.service( 'MyService' , MyService); |
ES6 class和ES5中的构造函数是一回事.
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步