AngularJS: Service vs provider vs factory

AngularJS: Service vs provider vs factory

技术背景

在AngularJS开发中,Service、Factory和Provider是用于创建和管理可复用对象的重要概念,它们都基于依赖注入机制,帮助开发者在不同组件间共享代码和数据。理解它们的区别和使用场景,有助于写出更高效、可维护的代码。

实现步骤

Services

  • 语法module.service('serviceName', function);
  • 结果:当把serviceName作为可注入参数声明时,会得到传入service函数的实例,即new FunctionYouPassedToService()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 创建服务
var app = angular.module('myApp', []);
app.service('servicePattern', function() {
this.firstName = 'James';
this.lastName = 'Bond';
this.greet = function() {
console.log('My Name is ' + this.firstName + this.lastName);
};
});

// 在控制器中使用服务
app.controller('myServiceCtrl', function($scope, servicePattern) {
servicePattern.greet();
});

Factories

  • 语法module.factory('factoryName', function);
  • 结果:当把factoryName作为可注入参数声明时,会得到调用传入module.factory的函数引用所返回的值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 创建工厂
var app = angular.module('myApp', []);
app.factory('factoryPattern', function() {
var data = {
'firstName': 'Tom',
'lastName': 'Cruise',
greet: function() {
console.log('hello!' + this.firstName + this.lastName);
}
};
return data;
});

// 在控制器中使用工厂
app.controller('myFactoryCtrl', function($scope, factoryPattern) {
factoryPattern.greet();
});

Providers

  • 语法module.provider('providerName', function);
  • 结果:当把providerName作为可注入参数声明时,会得到(new ProviderFunction()).$get()。构造函数在调用$get方法之前被实例化,ProviderFunction是传入module.provider的函数引用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 创建提供者
var app = angular.module('myApp', []);
app.provider('providerPattern', function providerConstructor() {
this.firstName = 'Arnold ';
this.lastName = ' Schwarzenegger';
this.greetMessage = ' Welcome, This is default Greeting Message';
this.setGreetMsg = function(msg) {
if (msg) {
this.greetMessage = msg;
}
};
this.$get = function() {
var firstName = this.firstName;
var lastName = this.lastName;
var greetMessage = this.greetMessage;
var data = {
greet: function() {
console.log('hello, ' + firstName + lastName + '! ' + greetMessage);
}
};
return data;
};
});

// 配置提供者
app.config(function(providerPatternProvider) {
providerPatternProvider.setGreetMsg(' How do you do ?');
});

// 在控制器中使用提供者
app.controller('myProviderCtrl', function($scope, providerPattern) {
providerPattern.greet();
});

最佳实践

  • Factory:适用于创建可复用的工具函数、数据处理逻辑等,返回值可以是任意类型,包括对象、函数等。
  • Service:适合创建自定义类型的对象,使用this关键字添加属性和方法,通常用于封装业务逻辑。
  • Provider:当需要在应用启动前对服务进行全局配置时使用,例如设置API URL、默认参数等。

常见问题

  • this关键字的使用问题:在Service中使用this时,要注意函数调用时的上下文,避免this指向错误。可以使用bind方法来绑定正确的上下文。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
angular.service('ScoreKeeper', function($http) {
this.score = 0;
this.getScore = function() {
return this.score;
};
this.setScore = function(newScore) {
this.score = newScore;
};
this.addOne = function() {
this.score++;
};
});

// 正确调用方式
$http.get('/score').then(ScoreKeeper.setScore.bind(ScoreKeeper));
  • 注入限制问题Value可以注入到ServiceFactory中,但不能注入到Provider的创建函数中,不过可以注入到Provider$get函数中。
1
2
3
4
5
6
7
8
9
10
11
var myApp = angular.module('MyAppName', []);
myApp.value('b', {name: 'Jones'});

myApp.provider('greetProvider', function() {
// 这里不能注入b
this.$get = function(b) {
// 这里可以注入b
this.lastName = b.name;
return this;
};
});

AngularJS: Service vs provider vs factory
https://119291.xyz/posts/2025-05-09.angularjs-service-provider-factory-comparison/
作者
ww
发布于
2025年5月9日
许可协议