Angular.js:是否无法将已解决的承诺的属性分配给$ scope?

时间:2013-05-29 10:43:08

标签: javascript angularjs q

我正在尝试重构一直使用Ajax获取某些serverdata的应用程序,然后将其附加到$rootScope,以便在引导应用程序之前获取控制器和服务,并且我一直在尝试使用promises使用$q

plnkr:http://plnkr.co/edit/22yQUlyE9nbQ0WVjxWxY

在那个plnkr中,我试图让服务返回一些数据,供一些控制器使用。

app.service('data', function($q, $window, $timeout) {
   var promise = $q.defer();
   promise.promise.foo = 'Dang!';
   $timeout(function() {
     console.log('resolve promise');
     promise.resolve({
      foo: 'bar',
      baz: 'zot'
     });
   }, 1000);
   console.log('return promise');
   return promise.promise
});

我正在使用$ routeProvider的resolve-property,如下所示

app.config(function($routeProvider) {
  $routeProvider.when('/', {
    controller: 'MainController',
    templateUrl: 'data.html',
    resolve: {
      data: 'data'
    }
  });
});

但是当我尝试将已解决的承诺的'foo'属性分配给我的一个控制器中的$ scope时,它就出错了。

app.controller('MainController', function($scope, data) {
  $scope.main = data.foo;
});

app.controller('Controller1', function($scope, data) {
  $scope.controller1 = data;
});

当promise解析后,$scope未得到更新,实际承诺对象的foo属性最终会在$scope上显示,如http://plnkr.co/edit/22yQUlyE9nbQ0WVjxWxY?p=preview上所示

我是否正在通过为$scope分配承诺的属性来做我绝对不应该做的事情?我的印象是路线的resolve-property意味着在承诺解决之前没有任何东西被初始化。

1 个答案:

答案 0 :(得分:3)

看起来正在发生的是时间问题。实例化服务时,它会设置超时。然后实例化控制器,将$scope.main设置为data的属性,但不设置为data引用的对象。

当您将此嵌套属性分配给另一个引用时,您将无法跟踪对父引用的更改,因为对该属性的此引用将始终指向旧值。在data中引用同一对象(Controller1)时,不会遇到此问题,因为引用指向的对象的属性只是被覆盖。如果resolve方法正在向数据写入新对象,则会看到相同的问题,因此更改引用。

分步骤:

1)数据服务被实例化并返回一个对象,该对象具有指向值为foo的字符串对象的单个属性Dang!

2)MainController被实例化,并将范围的main属性设置为数据服务的foo属性中保存的对象。这是重要的部分,因为main属性只知道对象Dang!

此外,实例化Controller1并将作用域的controller1属性设置为作为数据服务的对象。

3)计时器触发并覆盖数据对象的属性到其他一些属性。由于data处的对象未被替换,controller1可以看到每个属性的新值。由于main指向包含值Dang!的对象,因此没有任何变化。它只会注意到如果它引用的对象的值发生了变化,并且由于javascript中的字符串值是不可变的,所以它无法更改。

要解决您的情况,如果您希望范围的属性随服务更改而更改,则需要绑定到您的服务并引用表达式中的属性。