2

在我的AngularJS應用程序中,我有一個會話服務對象,其中包含像當前用戶,他們的偏好,他們所屬的當前公司以及他們正在使用的當前主題等內容。當我的應用程序中有很多地方需要獲取這些數據時,請參閱會話服務。將會話數據與其他角度指令和控制器同步

因爲這些變量在服務中,所以我無法使用範圍監視來檢測更改。相反,我決定使用觀察者模式。應用程序中的各個位置(如其他服務,指令,控制器等)將向會話服務註冊自己,並提供一個回調,以便在會話更改時執行。

例如,如果用戶更改其主題,將會通知使用自定義指令的index.html中的<style>元素,並且會重新創建新顏色的所有覆蓋CSS規則。例如,當用戶的頭像被更新時,主菜單欄控制器將被通知刷新並重新繪製頭像。像這樣的東西。

顯然,在各種控制器,指令等使用它之前,Session中的數據至少需要刷新一次。要求會話服務獲取其會話數據的自然地點在應用程序級模塊的run塊中。這工作得很好,但我認爲它也不是最好的地方。

我注意到的一個問題是,當Firebug打開時,加載事件的異步特性會導致排序問題。例如,在<style>元素上運行的指令將在應用程序的運行塊中刷新會話服務後運行...這意味着在按F5後主題將不會更新,因爲回調是在數據初始化後註冊的。我必須在這裏調用手動刷新以保持同步,但如果我這樣做了,它可能會在訂單不同的時間執行兩次!這是個大問題。我認爲這個問題不僅僅與Firebug有關......它可能在任何情況下發生,但是Firebug似乎會造成它持續一些,這很糟糕。

回顧一下...這種異步的排序是好的:

  1. 主題指令寄存器回調會議
  2. 菜單欄應用程序控制器註冊回調會議
  3. Session.refresh()被調用.run塊。

這種異步的排序是壞:

  1. 菜單欄應用控制器寄存器回調會議
  2. Session.refresh()被調用.run塊。
  3. 主題指令註冊回撥Session,,但自從Session.refresh()已被執行以來,回調沒有得到執行。

因此,而不是使用觀察者模式,或通過run塊刷新會話狀態,什麼是最好的方式來設計服務等,從而使會話數據總是會得到刷新後(或可能之前)應用程序的其他各個部分都需要它嗎?是否有某種事件可以掛鉤,在執行指令和控制器之前執行,而不是運行塊?

如果我的方法通常是合理的,我可以添加什麼來真正使它按照它應該的方式工作?

謝謝!

+0

從服務器執行此會話數據負荷? – Chandermani

+0

當然:)它讓一個http get/session,獲得所有這些項目。它目前在運行塊中執行此操作,但我願意接受其他建議。無論何時應用程序需要會話再次刷新,它都可以手動調用相同的方法。 – egervari

+0

一般來說,Angular的整個交易是直接訪問數據,並讓內部'$ digest'處理更新其他數據。你的模塊能夠自己訪問會話變量嗎? – willoller

回答

1

在angular.js你必須使用全局變量的2路:

  1. 使用$ rootScope
  2. 使用服務

使用$ rootScope是很容易的,你可以簡單地注入它進入任何控制器並在此範圍內更改值。所有全局變量都有問題! 服務是一個單身(你需要什麼)!

我覺得你的情況,你可以使用

$ rootScope

而且

$範圍。$看

answer

+0

是不是使用rootScope一般認爲不好的做法? – egervari

+0

我認爲最簡單的方式,不錯。 –

+0

我早些時候以這種方式工作,但我認爲這可能是不好的做法,因爲別的東西可能會與它發生衝突。如果其他東西覆蓋'$ rootScope.currentTheme',那會不會是壞事?保護服務不是更好嗎? – egervari

0

是否有一個原因,你不能直接訪問的變量是這樣的:

app.factory('SessionService', function() { 
    var items = { 
     "avatar": "some url" 
    }; 
    return items; 
}); 

var MainController = [$scope, 'SessionService', function($scope, SessionService){ 
    $scope.session = SessionService; 

    $scope.modifyAvatar = function(url){ 
     $scope.session.avatar = "some new url"; 
    }; 
}]; 

var HeaderController = [$scope, 'SessionService', function($scope, SessionService){ 
    $scope.session = SessionService; 

    // You probably wouldn't do this, you would just bind 
    // to {{session.avatar}} in your template 
    $scope.getAvatar = function(){ 
     return $scope.session.avatar; 
    }; 
}]; 
+0

我使用觀察者模式的原因是有些值是實際上是在服務器上添加/計算的,而不是客戶端。所以在某些情況下,可能會在我將它推送到服務器的同時在本地更新會話,但是很多時候我需要調用'/ session'來獲取服務器看到的當前狀態,因爲否則我只是在服務器上覆制邏輯......或者我甚至無法獲取新數據,因爲客戶端找不到好的方法。這是服務器端業務層的東西。 – egervari

+0

在這種情況下,您的SessionService(或其他適當的服務)應該是客戶端和服務器之間的中介。將獲取服務器數據的邏輯放在那裏,並提供一個覆蓋緩存並從服務器檢索數據的公共方法。這樣,服務可以隨時調用數據庫,並且其他服務或控制器可以請求SessionService從數據庫中刷新。 – willoller

+0

你不需要看這個函數 - 你調用函數並綁定結果。這樣你就不必看任何東西,因爲綁定被更新了。 – willoller

相關問題