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(); } } }
這樣,只用在登入進行系統的時候獲取一次選單,後面都不用進行向後臺的請求了。閃爍的問題也就消失了。