乐趣区

Angular service的单例模式

问题描述
前台在的菜单,需要向后台进行请求,但是这样就造成每次点击一个菜单都会重新请求,造成菜单会出现短暂闪烁的情况,所以考虑使用 service 的单例模式来解决这个问题。
service 单例模式
在 angularjs 中,service 默认都是单例的,但是在 angular 中,取消了这种默认。虽然我们说单例模式是好的,但是很多时候我们真的需要 service 是单例的吗?
比如我们经常使用的表格,大部分情况下,我们只是需要将信息展示出来,并不需要使用 service 对其进行缓存,因为它不会被别的模块所使用。
那么,在 angular 中如何使 service 为单例的呢?
实现
其实,在 angular6 之前,如何我们想声明一个 service 供全局使用,是这样设置的:
服务:
export class TestService {}
根模块:
@NgModule({
declarations: […],
providers: [TestService],
bootstrap: [AppComponent]
})
export class AppModule {}
我们需要在 @NgModule 中去声明 providers,将 service 共全局使用,成为单例。
但是从 angular6 开始,单例模式又变成了一个首选方式。
所以,只要我们使用 angular-cli 的命令创建 service 的时候,就会默认创建如下部分:
@Injectable({
providedIn: ‘root’,
})
这时,就声明该 service 在整个项目的模块下是单例的了。
当然,此时使用原来在 @NgModule 中 providers 的方式也是可以的。
我的应用
我的目的是避免重复请求后台,所以基本思路就是在一次请求后台之后,将请求结果交给 service 保管,然后,然后下次请求就直接获取 service 中的数据就可以了。
@Injectable({
providedIn: ‘root’,
})
export class MenuService {
private baseUrl = ‘menu’;
private currentMenuList: Array<Menu>; // 这里存储所有的菜单

constructor(private http: HttpClient) {
}

/**
* 请求后台,获取所有菜单
*/
getAll() {
return this.http.get<Menu[]>(this.baseUrl);
}

/**
* 设置当前菜单列表
* @param menuList 菜单列表
*/
setMenuList(menuList: Array<Menu>) {
this.currentMenuList = menuList;
}

/**
* 获取当前菜单列表
*/
getMenuList() {
return this.currentMenuList;
}
}
export class LeftControlComponent implements OnInit {
menuList: Menu[]; // 菜单

constructor(private userService: UserService,
private menuService: MenuService) {
}

ngOnInit() {
this.initMenu();
}

/**
* 初始化菜单
*/
initMenu() {
// 当前菜单为空的时候,重新请求菜单
if (!this.menuService.getMenuList() || this.menuService.getMenuList().length === 0) {
this.userService.getCurrentLoginUser()
.subscribe((data: User) => {
this.menuList = data.role.menuList;

// 将获取的菜单交由 service 保存
this.menuService.setMenuList(this.menuList);
}, () => console.log(‘network error!’));
} else {
// 直接使用保存的菜单
this.menuList = this.menuService.getMenuList();
}
}
}
这样,只用在登录进行系统的时候获取一次菜单,后面都不用进行向后台的请求了。闪烁的问题也就消失了。

相关参考:https://segmentfault.com/a/11…https://angular.cn/guide/sing…

退出移动版