我正在尝试重构一直使用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意味着在承诺解决之前没有任何东西被初始化。
答案 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中的字符串值是不可变的,所以它无法更改。
要解决您的情况,如果您希望范围的属性随服务更改而更改,则需要绑定到您的服务并引用表达式中的属性。