2013-05-29 79 views
1

我試圖重構已使用Ajax來獲取一些serverdata,然後將其連接到$rootScope爲控制器和服務自舉應用前,拿起一個應用程序,我一直在試圖用$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' 
    } 
    }); 
}); 

但是,當我試圖解析的承諾$範圍的「富」屬性分配在我的控制器之一是隻是出錯了。

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

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

$scope時承諾解決沒有更新和實際承諾對象的foo財產上$scope最終成爲可以http://plnkr.co/edit/22yQUlyE9nbQ0WVjxWxY?p=preview

可以看出所以我在做的事情我絕對不應該在此通過將承諾的屬性分配給$scope?我的印象是,這條路線的解析性意味着,在承諾解決之前,什麼都不應該初始化。

+0

似乎你有時會有最好的一站,並重新運行預覽版的實際工作 – ivarni

回答

3

看起來發生了什麼是計時問題。當服務被實例化時,它設置超時。然後控制器被實例化,設置$scope.maindata的屬性,但不是data引用的對象。

當您將此嵌套屬性分配給另一個引用時,將失去跟蹤對父引用的更改的能力,因爲此屬性的引用將始終指向舊值。當您引用Controller1中的同一個對象(data)時,您不會遇到此問題,因爲引用指向的對象的屬性被簡單地覆蓋。如果解析方法正在將新對象寫入數據,則會看到相同的問題,因此請更改引用。

分成以下步驟:

1)中的數據服務被實例化,並且具有與返回在與值Dang!一個字符串對象指向單個屬性foo的對象。

2)MainController被實例化並將作用域的main屬性設置爲數據服務的foo屬性中保存的對象。這是重要的部分,因爲主要財產只知道對象Dang!

此外,Controller1被實例化並將作用域的controller1屬性設置爲作爲數據服務的對象。

3)定時器觸發並覆蓋數據對象的屬性爲其他一些屬性。由於data上的對象未被替換,因此controller1可以在每個屬性中看到新值。由於main指向保存值Dang!的對象,因此沒有任何變化。如果引用中的對象的值發生了變化,並且由於javascript中的字符串值是不可變的,所以它只會注意到更改,因此無法更改。

要解決您的情況,如果希望範圍的屬性隨服務更改而更改,則需要綁定到服務並引用表達式中的屬性。

+0

好吧,所以我猜這個$ q承諾並不像我想的那樣工作。我想到,一旦承諾解決了,角就會把承諾視爲一個普通的對象。所以你基本上說的是,一旦它的聲明和只有延遲實際上讀取它,直到它在定時器之後被解決,我的控制器纔會交給未來? – ivarni

+0

那麼,我說了一點錯誤,控制器交給了未來的參考,並有一個不會改變的屬性。這解釋了我所看到的。 – ivarni

+0

就是這樣。當某個新對象發生解析時,該屬性在'data'對象上被覆蓋,但原始賦值是對舊對象的引用。 –