在AngularJS中从服务获取数据后,如何更新$ scope的最佳方法

时间:2014-11-05 12:15:22

标签: javascript angularjs service scope angularjs-scope

我在angularJS的一个小应用程序中工作,使用对API服务的调用来获取,显示和操作数据。

一开始一切都很顺利,但是当我不得不在不同控制器下的应用程序的不同部分显示相同的数据时,我开始将所有API调用移动到工厂以共享该数据并控制不再创建另一个请求,如果没有必要。

但随之而来的是一个不同的问题:发出请求,将数据放入正确的$ scope中,但在我手动点击某处与视图交互之前,视图中没有反映任何更改。

我一直在尝试使用$ scope。$ apply和$ scope。$ watch;我设法让它发挥作用,但现在我发现自己在许多地方使用延迟,这对我来说似乎非常不自然。

我将向您展示用户个人资料的代码,以便了解我所说的内容。

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

<title>Demo</title>
</head>
<body ng-app="app" ng-controller="DashboardCtrl">

<div ng-init="getOwnProfile()">
  <h1>My account</h1>

  <form class="inline-form" role="form">
      <input type="hidden" value="2" name="id"/>

      <div class="form-group has-error">
          <ul class="input-grp-2">
              <li><input name="first_name" type="text" ng-model="profile.first_name" placeholder="First name" /></li>
              <li><input name="last_name" type="text" ng-model="profile.last_name" placeholder="Last name" /></li>
          </ul>
      </div>
      <input name="phone" type="text" ng-model="profile.phone" placeholder="Phone number"/>

      <textarea name="information" rows="7">{{ profile.information }}</textarea>

      <a href="#" class="button btn-add-photo"><span class="glyphicon glyphicon-camera"></span> Add Photo</a>
      <input style="display: none" type="file" name="image" class="upload-photo" id="input_upload" accept="image/*"/>
  </form>
  <a href="" target="_self" class="button btn-green" ng-click="updateProfile(profile)">Submit Changes</a>

</div>

<script src="/js/app.js"></script>
<script src="/js/controllers/dashboard.js"></script>
<script src="/js/api.js"></script>
</body>
</html>

我使用的仪表板控制器:

$scope.profile = null;

$scope.getOwnProfile = function () {
    $scope.$watch( 'profile', function() {
        setTimeout(function () {
            $scope.$apply(function () {
                $scope.profile = API.getOwnProfile();
            });
        }, 100);
    })
};

API服务将配置文件设置为:

var APIService = {};

var ownProfile;

APIService.resetRenterProfile = function() {
    ownProfile = undefined;
};

APIService.getOwnProfile = function() {
    if (typeof ownProfile === 'undefined') {
        retrieveOwnProfile();
    }
    return ownProfile;
};

retrieveOwnProfile = function() {
    return Restangular.one('profile', null).get()  // GET: /profiles
        .then(function (profile) {
            ownProfile = profile;
        });
};

return APIService;

正如我所说,这有效,但我有两个问题。

1)获取数据并将其放入右侧范围内的每个控制器的右侧var中,但在用户对视图产生一些影响的内容之前,视图中不会显示任何$ scope数据,例如单击下拉菜单,选项卡等

2)我必须以毫秒为单位指定延迟,如果由于任何原因,对后端的API调用花费的时间比该延迟多,则在用户手动与视图交互之前,不会显示$ scope数据。

尽管它有效,我的印象是我以错误的方式做这件事,所以我想如果有人能指出我如何避免或改善这类问题。

非常感谢。

1 个答案:

答案 0 :(得分:0)

$scope.getOwnProfile = function () {
    $scope.profile = API.getOwnProfile();
};

retrieveOwnProfile = function() {
    ownProfile = $resource('profile').get();
};

上面的代码可以按你的意愿工作......为什么? 转到浏览器中的调试,看看执行时会发生什么: var result = $ resource()。get(); 你可以看到&#39;结果&#39;不会是通常的对象。并且angularjs本身将在结果发布后立即更新视图&#39;更新。