angular学习笔记(二十八)-$http(6)-使用ngResource模块构建RESTful架构

ngResource模块是angular专门为RESTful架构而设计的一个模块,它提供了‘$resource‘模块,$resource模块是基于$http的一个封装.下面来看看它的详细用法

1.引入angular-resource.min.js文件

2.在模块中依赖ngResourece,在服务中注入$resource

var HttpREST = angular.module(‘HttpREST‘,[‘ngResource‘]);
HttpREST.factory(‘cardResource‘,function($resource){
    return $resource(‘/card/user/:userID/:id‘,{userID:123,id:‘@id‘},{charge:{method:‘POST‘,params:{charge:true},isArray:false}})
});

3.$resource的参数:

$resource(url,{url参数},{自定义方法})

url: 必填,资源的基础url

url中带有 ‘:‘ 项的是根据第二个参数来进行配置的.

url参数: 选填,配置url中的带有 ‘:‘ 项的参数

eg:

(‘/card/user/:userID/:id‘,{userID:123,id:‘@id‘}),那么userID会被配置为123.

另外,在调用$resource()的方法的时候(比如get,query...),可以传入参数覆盖这里对url参数的配置,这在后面说得到它的方法的时候再详解

而id属性在后面讲第三个参数的时候讲解

自定义方法:

使用$resource获取到的资源,或者通过$resource实例化的资源,资源本身会具有一些方法,比如$save,第三个参数用于给资源添加自定义的方法:详见:http://www.cnblogs.com/liulangmao/p/3907032.html

4.$resource()的方法:

$resource()一共有以下5个方法:

get:

{method:‘GET‘}

一般用于获取某个资源:

query:

{method:‘GET‘,isArray:true}

一般用于获取一整套的资源,以数组形式返回

save:

{method:‘POST‘}

一般用于保存某个资源,有可能是新建的资源,也有可能是更新现有的资源

remove:

{method:‘DELETE‘}

一般用于删除某个资源

delete:

{method:‘DELETE‘}

一般用于删除某个资源

eg:

1.首先通过$resource创建一个服务:

var HttpREST = angular.module(‘HttpREST‘,[‘ngResource‘]);

HttpREST.factory(‘cardResource‘,function($resource){
    return $resource(‘/card/user/:userID/:id‘,{userID:123,id:‘@id‘},{charge:{method:‘POST‘,params:{charge:true},isArray:false}})
});

这个cardResource服务,返回的是一个对象,对象有get,query,save,remove,delete五个方法

2.然后我们通过cardResource这个服务,来创建另外一个获取资源的服务:

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
        },
        query:function(){
            var defer = $q.defer();
            cardResource.query(function(data,headers){
                defer.resolve(data);
            },function(data,headers){
                defer.reject(data);
            });
            return defer.promise
        }
    }
});
httpCard这个服务返回的对象有两个方法,一个getById方法,用于通过id加载资源,一个query方法,用于获取全部的资源.

然后来讲解一下get方法和query方法的用法:

get和query方法都是GET类型的请求,他们的调用方式是相同的:

cardResource.action([parameters], [success], [error])

[parameters]: 可选. 一个json对象,用于配置url里的参数,比如这里写了{id:cardID},那么提交的请求url就是 ‘/card/user/123/cardID‘.

可以不填,不填就直接按照$resource()里的url来提交,注意,不填的话,不需要给个空,可以直接写success回调,angular能够判断出它没有填第一个参数,而不是死板的按照顺序来解读参数.

[success]:可选. 请求成功后的回调函数.回调接受2个参数(注意这里和$http有所不同):

function(data,headers){

//data是请求到的内容

//headers是响应头

}

[error]:可选. 请求失败后的回调.回调接受1个参数

function(httpResponse){

//httpResponse暂不知道是什么. 反正是和响应有关

}

凡是通过$resource返回的对象,一定是json格式的,如果后台返回的数据不是json,$resource也会按照自己的方式处理成json格式,比如后台返回字符串‘我爱你‘,那么如果是get方法,得到的数据就是:

{
0:我,
1:爱,
2:你
}

而query方法定义了isArray为true,所以他的返回值必须是数组,并且数组里的每个值都必须是json格式的对象.如果返回的是字符串‘我爱你‘,那么如果是query方法,得到的数据就是:

[

{0:‘我‘},

{0:‘爱‘},

{0:‘你‘}

]

如果返回的是一个json对象{name:‘code_bunny‘},那么得到的数据就是:

[{name:‘code_bunny‘}]

所以,在后台最好就做好相应的处理,按照规范格式返回数据

3. 在控制器中使用httpCard服务来获取资源:

HttpREST.controller(‘Card‘,function($scope,httpCard,cardResource){
    //通过id获取银行卡
    $scope.card_1 = httpCard.getById(1);
    $scope.card_2 = httpCard.getById(2);
    $scope.card_3 = httpCard.getById(3);
    //获取所有的银行卡
    $scope.cards = httpCard.query();

});
  <span>{{card_1[‘name‘]}}</span>
  <span>{{card_1[‘amount‘]}}</span>
  <br/>
  <span>{{card_2[‘name‘]}}</span>
  <span>{{card_2[‘amount‘]}}</span>
  <br/>
  <span>{{card_3[‘name‘]}}</span>
  <span>{{card_3[‘amount‘]}}</span>
  <br/>

node:

var cards = [
    {
        id:1,
        name:‘建设银行‘,
        amount:0
    },
    {
        id:2,
        name:‘中国银行‘,
        amount:0
    },
    {
        id:3,
        name:‘上海银行‘,
        amount:0
    }
];

app.get(‘/card/user/123/:id‘,function(req,res){
    var data = cards[req.params.id-1];
    setTimeout(function(){res.send(data)},2000)
});
app.get(‘/card/user/123‘,function(req,res){
    res.send(cards)
});

关于card_1...cards明明是promise对象,但视图中却正确显示了资源的问题,请参考:http://www.cnblogs.com/liulangmao/p/3907307.html

4. 在控制器中使用cardResource服务的save方法来更新资源:

HttpREST.controller(‘Card‘,function($scope,httpCard,cardResource){
    $scope.card_3 = httpCard.getById(3);
    //更新id为3的银行卡
    $scope.updataCard = function(){
        $scope.card_3.then(function(data){
            data.name=‘工商银行‘;
            cardResource.save(data);
            //data.$save()
        });
    };
});

<button ng-click="updataCard()">更新id为3的银行卡</button>
  <br/>

<span>{{card_3[‘name‘]}}</span>
  <span>{{card_3[‘amount‘]}}</span>

node:(这段nodejs同时处理了charge和save)

var url = require(‘url‘);app.post(‘/card/user/123/:id‘,function(req,res){
    var index = req.params.id-1;
    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]);
});

点击后→

cardResource.save(data) 和 data.$save()在这里,两者是等价的.但是在有参数的时候,他们接受的参数其实是不同的:

使用cardResource.save([parameters], postData, [success], [error])方法时,可以接受四个参数:

[parameters]: 可选.用于配置url参数,比如配置{userID:124},那么请求url就会变成 ‘card/user/124/3‘,其中的3,还是从请求体的id属性获取的.

同样,如果没有参数需要配置,是不要填空的.不存在顺序一一对应.可以直接把postData作为第一个参数.

postData: 必填. 发送的请求体. save方法是post请求,必须要带有请求体.

[success]:选填. 响应成功后的回调函数,参数同get方法成功回调里的参数

[error]:选填. 响应失败后的回调函数.参数同get方法失败回调里的参数

使用data.$save([parameters], [success], [error])方法时,可以接受三个参数:

[parameters]: 可选.注意它不是用于配置url的参数的.它是用来设置url?后面的参数的! 比如设置{name:‘code_bunny‘},那么请求url就会变成‘card/user/123/3?name=code_bunny‘,

通过$save方法来调用save方法,是不能够配置url参数的.它直接就是提交资源自己.

同样,如果没有参数需要配置,是不要填空的.不存在顺序一一对应.可以直接把[success]作为第一个参数.

[success]:选填. 响应成功后的回调函数,参数同get方法成功回调里的参数

[error]:选填. 响应失败后的回调函数.参数同get方法失败回调里的参数

至于为什么要在then回调里处理,为什么save后视图会自动更新,请查看:http://www.cnblogs.com/liulangmao/p/3907307.html 以及 http://www.cnblogs.com/liulangmao/p/3907032.html

5. 在控制器中使用cardResource服务的save方法来新建资源:

(1)新建带有id的资源:

    //添加id为4的银行卡
    $scope.addCard4 = function(){
        var card_4 = new cardResource();
        card_4[‘id‘] = 4;
        card_4[‘name‘] = ‘浦发银行‘;
        card_4[‘amount‘] = 0;
        card_4.$save(function(data){$scope.card_4=data});        //cardResource.save(card_4,function(data){$scope.card_4=data});
    };
  <span>{{card_4[‘name‘]}}</span>
  <span>{{card_4[‘amount‘]}}</span>

node:(这段nodejs同时处理了charge和save)

app.post(‘/card/user/123/:id‘,function(req,res){
    var index = req.params.id-1;
    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]);
});

点击后→

新建资源需要通过new cardResource(), 这样它就是$resource()的实例,就拥有了$save,$charge等资源的方法:

card_4.$save(function(data){$scope.card_4=data});

cardResource.save(card_4,function(data){$scope.card_4=data});

上面已经说过了,这两种写法自然是等价的.但这里的回调里需要给$scope_card_4进行赋值,因为原来的$scope下是没有card_4这个变量的.

(2)新建没有id的资源:

    //添加没有id的银行卡
    $scope.addCard = function(){
        var newCard = new cardResource();
        newCard[‘name‘] = ‘农业银行‘;
        newCard[‘amount‘] = 0;
        newCard.$save(function(data){$scope.card_5=data});        cardResource.save(newCard,function(data){$scope.card_5=data});        //newCard.$save(function(data){$scope.card_5=data});
    };
<button ng-click="addCard()">添加一张不指定id的银行卡</button>
<br/>
<span>{{card_5[‘name‘]}}</span>
<span>{{card_5[‘amount‘]}}</span>

node:

app.post(‘/card/user/123‘,function(req,res){
    var index = cards.length;
    cards[index] = req.body;
    res.send(cards[index]);
});

点击后→

cardResource.save(newCard,function(data){$scope.card_5=data});newCard.$save(function(data){$scope.card_5=data});上面已经说过了,这两种写法自然是等价的.但这里的回调里需要给$scope_card_5进行赋值,因为原来的$scope下是没有card_5这个变量的.

(1)和(2)的区别在于:

资源是否有id,他们请求的路径是不同的.没有id的资源会请求‘card/user/123‘,而有id的资源会请求‘card/user/123/id‘,这在node里的处理是不同的.

在$resource中,基本url里面的 :id 这类通过参数指定的值,如果没有传入参数,那么它提交的路径里就不会包含这一项,比如:

return $resource(‘/card/user/:userID/:id‘,{userID:123,id:‘@id‘})
  当使用query方法时,是没有id值的,get请求的路径就是/card/user/123

但是在node里面不是这样的:

app.get(‘/card/user/123/:id‘,function(req,res){
//这个只能处理带有id值的get请求,没有id请求不能被匹配到处理
});
app.get(‘/card/user/123‘,function(req,res){
//这个用来处理没有id的get请求
});
app.post(‘/card/user/123/:id‘,function(req,res){
//这个只能处理带有id值的post请求,没有id请求不能被匹配到处理
});
app.post(‘/card/user/123‘,function(req,res){
//这个用来处理没有id的post请求
});

所以,处理有id的资源的post请求和处理没有id的资源的post请求,在node里需要写不同的匹配规则,在这里,对于没有id的资源,我们仅作模拟,就把它按照顺序保存在数组最后,然后当然还是把它返回给客户端.

6. 在控制器中使用cardResource服务的delete方法来删除资源:

7. 在控制器中使用cardResource服务的自定义的charge方法来给资源进行充值操作:

angular学习笔记(二十八)-$http(6)-使用ngResource模块构建RESTful架构,布布扣,bubuko.com

时间: 2024-10-14 22:58:06

angular学习笔记(二十八)-$http(6)-使用ngResource模块构建RESTful架构的相关文章

angular学习笔记(二十六)-$http(4)-设置请求超时

本篇主要讲解$http(config)的config中的timeout项: $http({ timeout: number }) 数值,从发出请求开始计算,等待的毫秒数,超过这个数还没有响应,则返回错误 demo: html: <!DOCTYPE html> <html ng-app = 'HttpGet'> <head> <title>18.4 $http(2)</title> <meta charset="utf-8"

angular学习笔记(二十四)-$http(2)-设置http请求头

1. angular默认的请求头: 其中,Accept 和 X-Requested-With是$http自带的默认配置 2. 修改默认请求头: (1) 全局修改(整个模块) 使用$httpProvider依赖 var myApp = angular.module('MyApp',[]); myApp.config(function($httpProvider){ console.log($httpProvider.defaults.headers.common) //修改/操作$httpProv

angular学习笔记(二十八-附2)-$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('h

angular学习笔记(二十八-附1)-$resource中的资源的方法

通过$resource获取到的资源,或者是通过$resource实例化的资源,资源本身就拥有了一些方法,比如$save,可以直接调用来保存该资源: 比如有一个$resource创建的服务: var service = angular.module('myRecipe.service',['ngResource']); service.factory('Recipe',['$resource',function($resource){ return $resource('/recipe/:id',

angular学习笔记(二十五)-$http(3)-转换请求和响应格式

本篇主要讲解$http(config)的config中的tranformRequest项和transformResponse项 1. transformRequest: $http({ transformRequest: function(data){ //对前台发送的data进行处理 return data } }) 这个在测试的时候遇到了很大的问题.只要经过transformRequest函数处理,哪怕是不做任何处理,node后台都会报错,需要尝试使用php 2. transformResp

angular中使用ngResource模块构建RESTful架构

ngResource模块是angular专门为RESTful架构而设计的一个模块,它提供了'$resource'模块,$resource模块是基于$http的一个封装.下面来看看它的详细用法 1.引入angular-resource.min.js文件 2.在模块中依赖ngResourece,在服务中注入$resource var HttpREST = angular.module('HttpREST',['ngResource']); HttpREST.factory('cardResource

angular学习笔记(三十)-指令(2)

本篇主要讲解指令中的 restrict属性, replace属性, template属性 这三个属性 一. restrict: 字符串.定义指令在视图中的使用方式,一共有四种使用方式: 1. 元素: E 2. 属性: A 3. 样式类: C 4. 注释: M restrict的值可以是上面四个字母的任意一个或多个的组合. 不指定的话默认为A. 二. replace: 布尔值.是否将指令元素替换,可以有两个值: 1.true: 替换整个使用指令的元素 2.false: 不替换整个使用指令的元素,而

马哥学习笔记二十四——分布式复制快设备drbd

DRBD: 主从 primary: 可执行读.写操作 secondary: 文件系统不能挂载 DRBD: dual primay, 双主(基于集群文件系统的高可用集群) 磁盘调度器:合并读请求,合并写请求: Procotol:drbd数据同步协议 A: Async, 异步  数据发送到本机tcp/ip协议栈 B:semi sync, 半同步  数据发送到对方tcp/ip协议 C:sync, 同步  数据到达对方存储设备 DRBD Source: DRBD资源 资源名称:可以是除了空白字符外的任意

【Unity 3D】学习笔记二十八:unity工具类

unity为开发者提供了很多方便开发的工具,他们都是由系统封装的一些功能和方法.比如说:实现时间的time类,获取随机数的Random.Range( )方法等等. 时间类 time类,主要用来获取当前的系统时间. using UnityEngine; using System.Collections; public class Script_04_13 : MonoBehaviour { void OnGUI() { GUILayout.Label("当前游戏时间:" + Time.t