Stories

Detail Return Return

Angular service的單例模式 - Stories Detail

問題描述

前台在的菜單,需要向後台進行請求,但是這樣就造成每次點擊一個菜單都會重新請求,造成菜單會出現短暫閃爍的情況,所以考慮使用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在整個項目的模塊下是單例的了。

當然,此時使用原來在@NgModuleproviders的方式也是可以的。

我的應用

我的目的是避免重複請求後台,所以基本思路就是在一次請求後台之後,將請求結果交給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...

Add a new Comments

Some HTML is okay.