AngularJS 服务(Service)(超详细)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观
前言
在 AngularJS 开发中,服务(Service) 是实现代码复用、模块化设计的关键工具。它如同应用程序的“心脏”,负责处理数据获取、状态管理、第三方库集成等核心逻辑,而控制器、指令等其他组件则专注于界面交互或视图渲染。对于编程初学者和中级开发者而言,理解服务的设计思想和使用方法,是掌握 AngularJS 核心架构的重要一步。
什么是 AngularJS 服务?
AngularJS 服务是可注入的 JavaScript 对象,用于封装可重用的业务逻辑或 HTTP 请求等操作。它们通过 AngularJS 的依赖注入(Dependency Injection)机制,被控制器、指令、过滤器或其他服务调用。
服务的核心特点
- 单例模式:每个服务在 AngularJS 应用中仅被实例化一次,确保数据和状态的全局一致性。
- 模块化:服务与视图逻辑分离,避免代码耦合。
- 可测试性:通过模拟(Mock)服务,可轻松进行单元测试。
比喻:
可以将服务想象为一家公司的“后勤部门”。例如,前端控制器是“前台接待员”,负责与用户交互;而服务则是“仓库管理员”,负责存储、处理和分发数据,确保前台无需关心数据的具体来源或处理逻辑。
如何创建 AngularJS 服务?
AngularJS 提供了多种方式创建服务,最常见的包括 factory、service、value 和 constant。以下通过代码示例逐一讲解。
1. Factory(工厂模式)
factory
是最灵活的服务创建方式,返回一个包含方法或属性的对象。
示例:创建一个天气服务
// 定义模块
var app = angular.module('weatherApp', []);
// 创建 WeatherService 工厂
app.factory('WeatherService', function() {
return {
getWeather: function(city) {
// 模拟异步请求
return new Promise((resolve) => {
setTimeout(() => {
resolve({ temperature: 25, condition: 'Sunny' });
}, 1000);
});
}
};
});
使用服务:在控制器中注入并调用
app.controller('WeatherCtrl', function($scope, WeatherService) {
WeatherService.getWeather('Beijing')
.then(function(response) {
$scope.weather = response;
});
});
2. Service(构造函数模式)
service
使用构造函数(通过 new
实例化)创建服务,适合需要复杂初始化逻辑或原型链继承的场景。
示例:创建一个计数器服务
app.service('CounterService', function() {
this.count = 0;
this.increment = function() {
this.count++;
};
});
使用服务:
app.controller('CounterCtrl', function($scope, CounterService) {
$scope.increment = function() {
CounterService.increment();
$scope.currentCount = CounterService.count;
};
});
3. Value 和 Constant(简单值注入)
value
和 constant
用于注入简单的数据对象或常量,区别在于 constant
可在配置阶段注入,而 value
仅在运行时可用。
示例:定义常量服务
app.constant('API_CONFIG', {
baseUrl: 'https://api.example.com',
timeout: 5000
});
app.value('UserPreferences', {
theme: 'dark',
language: 'en'
});
AngularJS 服务的应用场景
1. 数据共享与状态管理
服务是跨控制器共享数据的天然选择。例如,通过服务存储用户登录状态:
示例:用户认证服务
app.factory('Auth', function() {
var user = null;
return {
setUser: function(u) {
user = u;
},
getUser: function() {
return user;
}
};
});
在两个控制器中共享用户数据:
// 登录控制器
app.controller('LoginCtrl', function(Auth) {
Auth.setUser({ name: 'John', role: 'admin' });
});
// 仪表盘控制器
app.controller('DashboardCtrl', function($scope, Auth) {
$scope.user = Auth.getUser();
});
2. HTTP 请求封装
通过服务封装 $http
请求,避免在控制器中重复编写网络逻辑。
示例:封装 API 调用
app.factory('DataService', function($http) {
return {
fetchUsers: function() {
return $http.get('/api/users');
},
saveUser: function(user) {
return $http.post('/api/users', user);
}
};
});
3. 第三方库集成
服务可封装第三方库(如 Moment.js、Lodash),使其在 AngularJS 中可测试且易于维护。
示例:集成 Moment.js
app.factory('DateService', function() {
return {
formatDateTime: function(date) {
return moment(date).format('YYYY-MM-DD HH:mm');
}
};
});
服务的高级用法
1. 依赖注入(Dependency Injection)
服务之间可以互相依赖,通过参数名或 $inject
数组声明依赖关系。
示例:服务间依赖
app.factory('Logger', function() {
return {
log: function(msg) {
console.log('Logger:', msg);
}
};
});
app.factory('UserService', ['Logger', function(Logger) {
return {
createUser: function(user) {
Logger.log('Creating user:', user);
// 执行创建逻辑
}
};
}]);
2. 服务的生命周期
服务默认是单例的,因此其初始化逻辑(如异步请求)仅执行一次。若需在每次调用时执行特定操作,可通过方法实现。
示例:延迟初始化
app.factory('LazyService', function() {
var initialized = false;
return {
init: function() {
if (!initialized) {
// 执行初始化逻辑
initialized = true;
}
},
getData: function() {
this.init();
return 'Initialized data';
}
};
});
最佳实践与注意事项
1. 遵循单一职责原则
每个服务应专注于单一功能,例如:
AuthService
处理用户认证ApiService
封装 API 请求NotificationService
管理通知
2. 避免在服务中直接操作 DOM
服务应与视图逻辑分离,DOM 操作应由指令或控制器处理。
3. 使用依赖注入而非全局变量
避免通过全局变量共享数据,而是通过服务的依赖注入传递数据。
4. 测试服务的必要性
通过模拟(Mock)服务,可以独立测试业务逻辑。例如:
describe('WeatherService', function() {
beforeEach(module('weatherApp'));
it('should return weather data', inject(function(WeatherService) {
var result = WeatherService.getWeather('London');
expect(result).toBeDefined();
}));
});
结论
AngularJS 服务是构建大型应用的基石,它通过模块化、可复用的设计,帮助开发者降低代码复杂度并提升可维护性。无论是处理数据共享、HTTP 请求,还是集成第三方库,服务都能以清晰的逻辑和优雅的结构解决问题。
对于初学者,建议从简单服务入手(如 factory
或 value
),逐步过渡到复杂场景(如服务间依赖和异步操作)。对于中级开发者,可以深入探索服务与 AngularJS 生命周期的交互,以及如何通过服务优化应用性能。
掌握服务的设计模式,将使你在 AngularJS 开发中更加得心应手,为构建高效、可扩展的应用奠定坚实基础。