2013-08-19 48 views
2

我有一個「帳戶」服務,充當多個控制器和視圖中使用的集中式數據存儲。除了getter和setter方法之外,該服務還會保存與兩種類型的用戶相關的所有數據,即登錄用戶和匿名用戶。AngularJS。有關正確的雙向數據綁定服務的最佳實踐

這個服務背後的想法是,它應該被用作一個集中的數據結構,它將保持所有相關的視圖和控制器同步。例如:如果用戶登錄,將會知道他的電子郵件,並且所有'新聞訂閱'字段都可以預先填好。

我使用的當前設置如下。請注意,服務器上的每個異步調用都會返回一個承諾。

// The Service 
angular.module('A').provider('AccountService', [function() { 

    this.$get = function ($resource) { 

     var Account = { 
      getLoggedInAccountAsync : function() { 
       var Account = $resource(WebApi.Config.apiUrl + 'Account/Get'); 
       return Account.get(); 
      }, 

      getUserData : function() { 
       return Account.userData; 
      }, 

      setUserData : function (accountData) { 
       var merge = angular.extend((Account.currentAccountData || {}), accountData); 
       Account.currentAccountData = merge; 
      }  
     }; 

     return Account; 
    } 
}); 

// Our main app controller. Get's fired on every page load. 
angular.module('A').controller('MainController', ['AccountService', function (AccountService) { 

    var loggedInAccount = AccountService.getLoggedInAccountAsync(); 
    loggedInAccount.$then(loggedInAccountPromiseResolved); 

    function loggedInAccountPromiseResolved (response) { 
     if (response.data.isLoggedIn) { 
      AccountService.setAccountData(response.data); 
     } 
    }; 

    return $scope.MainController= this; 
}]) 

// Our specific controller. For example a newsletter subscription. 
angular.module('A').controller('SpecificController', ['AccountService', function (AccountService) { 
    this.getUserData = AccountService.getUserData; 
    return $scope.Controller = this; 
}]) 

// Newsletter subscription view 
<input id="email" type="email" name="email" ng-model="SpecificController.getUserData().UserName"/> 

使用上面的代碼確保每當我們使用該服務通過Controller.getUserData結合我們的數據()。屬性我們認爲它會保持同步,我們整個應用程序。

如果沒有定義.UserName值,或者如果在不合用戶的情況下根本沒有帳戶數據,上面的代碼也會拋出。解決這個問題的一個方法是使用空值將我們的'模板'對象'轉儲'到我們的服務中,這將確保鍵/值存在。另一種方法是使用觀察者,並讓我們的控制器'寫'給我們的服務,以防用戶填寫一個字段。

第一個選項給了我更多的靈活性,因爲我可以集中服務中的所有數據綁定,但它感覺骯髒,因爲您永遠不知道服務器數據會發生什麼,它可能會以不同的格式進來。

有沒有人有任何其他解決方案?我寧願不讓我的控制器將數據寫入服務。

謝謝你的時間!

回答

2

這裏有很多問題,我會盡我所能回答。

不,你在做什麼不是「最佳實踐」。

首先,模型應該直接注入到視圖中,並且在「$ scope」的幫助下維護該值是Controller的職責。你的「ng-model =」Controller.getUserData()。UserName「是不好的。在下面我注意到的博客文章結尾處有一個很好的例子:

其次,當你從服務,大多數情況下,答案是異步的,所以你最好看看Promise API。AngularJS的官方文檔並不總是很棒,有時候可以在谷歌組或博客文章中找到答案。

對於您的問題,這裏是一個很好的文章:http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/

+0

THX的鏈接! – chris

2
  1. 首先,如果你在AngularJS使用的服務,我們期待的服務器或任何一個呼叫可能不會立即返回數據。所以我們有兩種使用醜陋回調或美麗的方法$q

我更喜歡使用諾言,因爲它寫得更乾淨。我會重寫你的片段以更好的方式:

// Service 
angular.module('A').provider('AccountService', [function() { 

    this.$get = function ($resource, $q) { 

     var Account = { 
      getUserData : function() { 
       var d = $q.defer(); 
       d.resolve(Account.userData); 
       return d.promise; 
      }  
     }; 

     return Account; 
    } 
}); 

// Controller 
angular.module('A').controller('Controller', ['AccountService', function (AccountService) { 
    var init = function() { 
     getUserData(); 
    }; 

    var getUserData = function() { 
     AccountService.getUserData().then(function(data) { $scope.username = data; }); 
    }; 

    init(); 
    //return $scope.Controller = this; // you don't need to do this 
}]) 

HTML:

<input id="email" type="email" name="email" ng-model="username"/>