angular學習筆記(二十八-附2)-$http,$resource中的promise對象


下面這種promise的用法,我從第一篇$http筆記到$resource筆記中,一直都有用到:

HttpREST.factory('cardResource',function($resource){
    return $resource('/card/user/:userID/:id',{userID:123,id:'@id'},{charge:{method:'POST',params:{charge:true},isArray:false}})
});
HttpREST.factory('httpCard',function($q,cardResource){
    return {
        getById:function(cardID){
            var defer = $q.defer();
            cardResource.get({id:cardID},function(data,headers){
                defer.resolve(data);
            },function(data,headers){
                defer.reject(data);
            });
            return defer.promise
        }
    }
});
$scope.card_1 = httpCard.getById(1);
  <span>{{card_1['name']}}</span>
  <span>{{card_1['amount']}}</span>

 

這樣做的目的很顯然,由於后台返回數據需要時間,所以對card_1的賦值應該是異步的,所以getById方法返回的是一個promise,所以,card_1其實也是一個promise,我們把它打印出來可以看到:

1.同步打印:(還不等到后台返回數據就打印)

$scope.card_1 = httpCard.getById(1);
console.log($scope.card_1);

 

2.異步打印:(等到后台返回數據以后打印)

    $scope.card_1 = httpCard.getById(1);
    $scope.card_1.then(function(){console.log($scope.card_1)});

 

可以看到,同步打印的card_1,它的$$v是undefined,因為后台還沒有返回數據,但異步打印的card_1,它的$$v就是請求后返回的數據.

問題就出現了,card_1只有一個$$v屬性和一個then方法,它並沒有name屬性,也沒有amount屬性,但是在視圖中,<span>{{card_1['name']}}</span>確實渲染了.雖然我沒有看過源代碼,但是可以推測,視圖渲染card_1的時候,是使用了card_1的$$v對象來進行渲染的.所以訪問card_1['name'],其實是訪問了card_1的$$v['name'].

那么,如果card_1發生變化的時候,又是怎么處理的呢? 我嘗試了以下操作:

$scope.updataCard = function(){
  $scope.card_1.name='工商銀行';    //視圖不會發生變化
  $scope.card_1.$save()            //card_1沒有$save方法
};

發現直接操作card_1.name屬性,雖然card_1的name屬性確實發生了變化,但是,在視圖中它並沒有任何的變化.可見,視圖對於promise對象,監測的依然是它的$$v對象的屬性的變化,而它自己的屬性變化是沒有任何反應的.另外,card_1是promise對象,不是$resource返回的對象,card_1的$$v才是,所以,card_1當然也沒有$save方法

 

那么,如果我要更新card_1,修改card_1,到底應該怎么做的? 說到底,card_1的真身就是card_1的$$v對象,so,想要修改card_1,就要修改它的$$v對象:

$scope.updataCard = function(){
  $scope.card_1.$$v.name='工商銀行';
  $scope.card_1.$$v.$save();
};

這樣做,視圖就會被更新.但是這樣做有一個問題,上面已經看到了,$$v對象是在請求已經得到響應,得到返回的數據的時候才有的,在沒有得到響應前,$$v是undefined.所以,如果在還沒有得到響應前就執行了updataCard函數,這段代碼就會有問題.so,最好的方法是放在promise的then方法的回調函數的參數里:

    $scope.updataCard = function(){
        $scope.card_1.then(function(data){
            data.name='工商銀行';
            data.$save()
        });
    };

promise對象有一個then方法,then方法了接受三個回調,詳細參考:http://www.cnblogs.com/liulangmao/p/3907571.html ,這里只寫一個成功的回調,回調的參數data,也就是promise對象的$$v對象,then函數會在響應成功后被調用.所以,即便還沒有得到響應就觸發了updataCard方法,修改的操作還是會等到響應收到后才執行,這就是異步.

 

注意,這里的card_1是直接通過$resource返回得到的promise,但如果是通過angular路由的resolve方法返回的對象,在resolve的時候已經取了promise對象的$$v對象,然后再注入到控制器中.這樣得到的資源就不再是promise對象了,而已經是promise的$$v對象,后面都正常操作就可以了.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM