angular學習筆記(二十八-附1)-$resource中的資源的方法

詩&遠方發表於2014-08-12

通過$resource獲取到的資源,或者是通過$resource例項化的資源,資源本身就擁有了一些方法,$save,$delete,$remove,可以直接呼叫來儲存該資源: 

比如有一個$resource建立的服務:

var service = angular.module('myRecipe.service',['ngResource']);
service.factory('Recipe',['$resource',function($resource){
    return $resource('/recipe/:id',{id:'@id'});
}]);
service.factory('loadRecipes',['Recipe','$q',function(Recipe,$q){
    return function(){
        var defer = $q.defer();
        Recipe.query(function(recipes){
            defer.resolve(recipes)
        },function(err){
            defer.reject(err)
        });
        return defer.promise
    }
}]);
service.factory('loadRecipe',['Recipe','$q','$route','$routeParams',function(Recipe,$q,$route,$routeParams){
    return function(){
        var defer = $q.defer();
        Recipe.get({id:$route.current.params.recipeId},function(recipe){
            defer.resolve(recipe)
        },function(err){
            defer.reject(err)
        });
        return defer.promise
    }
}]);

然後我通過loadRecipe方法獲取到了一個recipe,修改了recipe後需要對它進行提交儲存,以下兩種方式是一樣的:

1. 通過$resource的save方法(第一個引數是請求提,第二個引數是請求完成後的回撥)

        Recipe.save($scope.recipe,function(){
            $location.path('/view/'+$scope.recipe.id)
        });

2. 由於recipe本身就是通過$resource獲取的資源,所以它擁有$save方法,$save方法裡的函式就是儲存成功後的回撥.

        $scope.recipe.$save(function(){
            $location.path('/view/'+$scope.recipe.id)
        });

除了通過loadRecipe獲取到的資源,通過$resource例項化的資源也有$save方法:

比如下面的recipe:

    $scope.recipe = new Recipe({
        ingredients:[{}]
    });
    $scope.save = function(invalid){
        if(invalid){
            return false
        }
        Recipe.save($scope.recipe,function(recipe){
            $location.path('/view/'+recipe.id)
        });
    };

$resource()中第二個引數{id:'@id'},表示url中的:id 將會使用資源的id屬性值,也就是recipe的id屬性值.

 

還可以通過$resource()第三個引數來給資源自定義方法:

return $resource('/card/user/:userID/:id',{userID:123,id:'@id'},{charge:{method:'POST',params:{charge:true},isArray:false}})

來分析一下這裡的第三個引數 {charge:{method:'POST',params:{charge:true},isArray:false}}

1.charge是自定義方法的名字,資源就可以通過$charge()來呼叫該自定義方法

2.charge屬性值是一個json物件,裡面有三個屬性:

   method: 該方法的請求方式: 'POST','GET','DELETE','PUT',等,這裡的請求方式可以自定義方法,$resource()返回的物件的get,query,save,remove,delete裡用到的只有'GET','POST','DELETE'三種請求方式,但是這裡自定義的方法,可以使用$http的所以請求方式. 所以,如果要自定義請求方式,也是通過自定義方法來建立的.

   params: 定義請求url後面的引數,這裡是{charge:true},就會向url?charge=true傳送請求

   isArray: 定義返回的資料的格式是否是陣列

3.charge屬性值除了2裡說到的三個屬性,還有所有$http裡所有可配置的項:

   headers:,

   transformRequest:,

   transformResponse:,

   cache:,

   timeout:,

   withCredentials:

這些項的意思和具體怎麼配置,請參考之前將$http的文章,他們是一致的.

eg:

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.addCharge = function(){
    $scope.card_1.then(function(card){
         card.$charge({amount:100});
    })
}

注意,card_1得到的是promise物件,而不是資源本身,要獲得實際的資源,要通過它的then方法裡的函式的引數來獲得.關於這個問題,請檢視: 

http://www.cnblogs.com/liulangmao/p/3907307.html

$charge裡的參數列示url後面的引數,也就是說:

card.$charge({amount:100}) 向/card/user/123/1?charge=turn&amount=100傳送了post請求,請求體就是card

請求url裡的1是因為在$resource()第二個引數中配置了{id:@id},所以就是card的id,

請求引數是charge=true是因為在$resource()第三個引數中配置了{charge:{params:{charge:true}}
請求方式是post是因為在$resource()第三個引數中配置了{charge:{method:'POST',params:{charge:true}}}

請求引數是amount=100是因為在呼叫card.$charge()的時候傳入了引數{amount:100}

資源的方法還有一個特性: 在請求完成後,會自動用返回值來填充呼叫方法的資源,繼而更新檢視.無需在回撥手動處理:

eg: 

html:

  <button ng-click="addCharge()">給建設銀行的卡充值100元</button>
  <br/>
  <span>{{card_1['name']}}</span>
  <span>{{card_1['amount']}}</span>
  <br/>

js:

    $scope.addCharge = function(){
        $scope.card_1.then(function(card){
            card.$charge({amount:100});
        })
    }

node:

app.post('/card/user/123/:id',function(req,res){
    var index = req.params.id ? req.params.id-1 : cards.length;
    var query = url.parse(req.url,true)['query'];
    if (query.charge){
        cards[index]['amount']+= Number(query['amount'])
    }
    else {
        cards[index] = req.body;
    }
    res.send(cards[index]);
});

點選充值後,後臺會給建設銀行卡新增100元,然後再把建設銀行卡這個資源返回給客戶端:

點選按鈕後:

我們可以看到,在card.$charge({amount:100})這個呼叫中,我們並沒有書寫回撥來改變$scope.card_1,但是檢視裡card_1['amount']確實發生了變化,原因是,

angular自動將返回值填充了card,而card是card_1的$$v屬性值(關於$$v請檢視http://www.cnblogs.com/liulangmao/p/3907307.html),所以檢視裡的card_1也會被更新.

 

相關文章