2

我有一个“帐户”服务,它充当多个控制器和视图中使用的集中数据存储。除了 getter 和 setter 方法之外,该服务将保存与两种类型的用户相关的所有数据,即登录用户和异常用户。

这个服务背后的想法是它应该被用作一个集中的数据结构,它将使所有相关的视图和控制器保持同步。例如:如果用户登录,他将知道他的电子邮件,并且所有“新闻订阅”字段都可以预先填写。

我使用的当前设置如下。请注意,服务器上的每个 Async 调用都将返回一个 Promise。

// 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().property 将我们的数据绑定到我们的视图时,它将在整个应用程序中保持同步。

如果例如未定义 .UserName 值,或者在异常用户的情况下根本没有帐户数据,上面的代码也会抛出。解决这个问题的一种方法是在我们的服务中使用空值“转储”我们的“模板”对象,这将确保键/值存在。另一种方法是使用观察者并让我们的控制器“写入”我们的服务,以防用户填写字段。

第一个选项给了我更大的灵活性,因为我可以将所有数据绑定集中在服务中,但感觉很脏,因为你永远不知道服务器数据会发生什么,例如它可能以不同的格式出现。

有没有人有任何其他的解决方案?我宁愿不让我的控制器将数据写入服务。

感谢您的时间!

4

2 回答 2

2

这里有很多问题,我会尽量回答。

不,您所做的不是“最佳实践”。

首先,模型应该直接注入到视图中,维护值是控制器的职责,在“$scope”的帮助下。您的 "ng-model="Controller.getUserData().UserName" 很糟糕。我在下面注意到的博客文章末尾有一个很好的示例说明该做什么。

其次,当你从服务中获取数据时,大多数情况下,答案都是异步的,所以你最好看看 Promise API。AngularJS 的官方文档并不总是很棒,有时可以在 google 群组或博客文章中找到答案。

对于您的问题,这是一篇很好的文章: http: //markdalgleish.com/2013/06/using-promises-in-angularjs-views/

于 2013-08-19T11:41:40.200 回答
2
  1. 首先,如果您在 AngularJS 中使用服务,我们希望调用服务器或任何可能不会立即返回数据的东西。所以我们有两种使用丑陋回调或美丽的方法$q

我更喜欢使用 promise,因为它写起来更干净。我会以更好的方式重写你的片段:

// 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"/>
于 2013-08-19T11:44:44.567 回答