1

我正在尝试重构一个一直使用 Ajax 获取一些服务器数据的应用程序,然后将其附加到$rootScope控制器和服务以在引导应用程序之前获取,并且我一直在尝试使用 Promise 这样做$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 的解析属性

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 解决并且实际 promise 对象$scope的属性结束时,不会更新,如http://plnkr.co/edit/22yQUlyE9nbQ0WVjxWxY?p=preview所示foo$scope

那么,我是否通过将 promise 的属性分配给 来做我绝对不应该在这里做的事情$scope?我的印象是路由的 resolve-property 意味着在 promise 解决之前不应该初始化任何东西。

4

1 回答 1

3

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

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

分解为步骤:

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

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

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

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

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

于 2013-05-29T13:24:28.803 回答