2013-01-09 45 views
18

最近有些同事和我正在討論AngularJS服務是否應該有狀態。我們提出了一些贊成和反對的觀點,並且希望得到關於這個問題的更多想法和反饋。在我的搜索中,我發現this,但似乎沒有提到任何明確的最佳做法。在沒有客戶端的世界中,服務不應該保持狀態,但我開始認爲它可能是可以接受的客戶端,因爲它有一個不同的問題。Angular服務應該有狀態嗎?

理由保持狀態服務:

  1. 的服務是不會被多個線程訪問。每個瀏覽器都有自己的服務實例。
  2. 允許該服務保持僅關注的狀態,而不是將其存儲在rootScope中。封裝不保持狀態

原因服務:

  1. 服務不再是冪等。調用函數可能會改變狀態,因此在根據服務狀態調用它時可能會有不同的結果。
  2. 我認爲總的來說這樣會更容易測試。

可能會解決「for services holding state」部分中#2的一種方法是在rootScope上設置一個appState對象,該對象包含應用程序的當前狀態。然後,所有的州都會集中在一個地方,然後在您的服務中將您需要的東西拉出來。我發現這一點,並想知道

回答

9

在AngularJS中,服務are passed in via factory function。基本上它們是可以包含某些狀態的對象(例如,用於緩存或存儲執行其操作所需的數據)。

可以兼顧有/無狀態的一個好的解決方案是返回包含狀態的對象的服務(實際上可能是函數)。

看看在$http服務:你可以得到這個服務調用

var x = $http({url:'...'}); 

的實例,然後通過

var result = x.get() //actually `$http.get` is shortcut of this operation 

同樣的,ngResource撥打:使用服務,您得到的對象與一些國家可以執行所需的操作。

所以基本上我認爲這是最好的選擇:從一個角度來說,通過將可以被動作修改的狀態移動到單獨的對象,而不是存儲在服務本身中,但可以在該對象中具有特定狀態,從而避免「副作用」能夠存儲自定義信息(如身份驗證信息等)。

+0

關於$ http和$資源的好處。另外,我喜歡你關於只存儲不會被服務調用的函數修改的狀態的想法(除了可能在初始化服務時)。 – testing123

13

這可能取決於你的意思是「狀態」,但在很多情況下,我認爲答案是肯定的:服務應該保持狀態。

例如,如果您有一個負責與API通信的服務,則該服務可以保持身份驗證狀態。

順便說一句,我不確定AngularJS服務有多少冪等關係 - 它們是單例,所以本質上有一些狀態。您可以(並且在某些情況下必須)在服務上創建冪等方法,但這是一個單獨的問題。

+0

關於保持認證狀態的好處。至於使服務冪等化,我的意思就像你提到的那樣具有冪等方法。感謝您的回答。 – testing123

+0

把它放在狀態中的好處就是你可以使用一個參考變量。正因爲如此,您可以創建一個複雜數據結構的清晰描述! – Exitos

1

IMO是的,服務可以有狀態。我認爲「可以」作爲服務可以被認爲是類似於經典的無客戶服務的提供者,但它也可能意味着完全不同的東西,在angularJS中。作爲應用程序中的rootScope-y單實例元素,它可以僅用於管理狀態,例如。在我的情況下,這使我能夠確保跨許多應用程序的狀態結構是相同的,即使它們各自的狀態結構是爲bootstrapping中的每個狀態結構定義的,但當模塊發生更改時,像會話狀態這樣的東西總是相同並更新。

-4

服務不應該有狀態的原因是當您有多個線程訪問服務時,它會導致競爭條件。

與狀態在服務的共同問題是:

  1. 線程1寫入狀態
  2. 螺紋2寫入狀態
  3. 線程1從狀態
  4. 線程2讀取讀取從狀態

線程1現在有錯誤的值。

這就是說,JavaScript目前是單線程的,所以你不會有像這樣的線程訪問問題。但是,如果我有一個服務將多個異步$ http調用寫入同一個服務變量,我會擔心。如果只是這樣,我可以晚上睡得更好,我會盡力寫出我所有的服務方法,因此它們是實際數據的傳遞。

相反,在維護服務中的狀態時,可以考慮儘可能將狀態置於後端。像「認證」,甚至寬度和高度的事情可以保持和查詢。這可以打開一些可能性,允許用戶遠離應用程序,回來並找到所有他們的偏好仍然設置和登錄。你可以存儲會話ID在cookie中,並將所有這些東西保存在後端。

如果你確實走了一條單獨的對象存儲狀態的路線,那麼當狀態發生變化時,你可以從服務中發出$:how to emit events from a factory。這可能會讓多個服務能夠修改統一的應用程序狀態,這是因爲狀態並未存儲在任何一個服務中(或者更糟糕的是分散在多個服務中)。

+2

你自己說過,javascript是單線程的,所以沒有競爭條件,即使通過webworkers也沒有,因爲webworkers可以共享對象的引用。你說的是後端,但是表示層的狀態沒有任何關係堅持不懈。 – mpm