AngularJS 学习笔记-第二章:与后端服务器通信

AngularJS能够通过XMLHttpRequest(XHR)和JSONP请求与各种后端交流,拥有通用的$http服务以进行XHR和JSONP调用,以及专门面向Restful后端接口的$resource服务

在本章中,将研究与后端通信的API与技术,特别是一下内容:

  • 使用$http服务进行基本的XHR调用,已经进行相应的测试
  • 利用$q服务提供的promise API进行有效的异步请求
  • 使用$resource工厂轻松与RESTful后端进行沟通
  • 根据后端需求构建自定义的与$resource类似的API

$http API快速导览

GET$http.get(url, config)
POST$http.post(url, data, config)
PUT$http.put(url, data, config)
DELETE$http.delete(url, config)
HEAD

$http.head

  • url: 调用目标URL
  • data:请求体中送出的数据
  • config:包含额外配置信息,对请求和响应都有影响

处理HTTP响应:请求可能成功或者失败,AngularJS提供两种方法以注册对应这两种结果的回调:success (200~299范围调用success,其余的状态吗则进入error)和error。

我们可以在调用$http方法返回的对象上,注册成功与失败的回调(callback)

  • data:实际的响应数据
  • status:响应的HTTP状态
  • headers:访问HTTP响应头信息的函数
  • config:请求触发时提供的配置对象

配置对象说明

  • method:所用的HTTP方法
  • url: 请求的目标URL
  • params: URL参数
  • headers: 额外的请求头
  • timeout:XHR请求终止前的超时时间(毫秒)
  • cache:XHR GET请求的缓存开关
  • transformRequest\transferResponse:在于后端交换数据前或交换后,对数据进行处理的数据变换函数
var base_url = 'http://localhost:8080/'
angular.module('myapp1', [])
    .controller('myController', function($scope, $http) {
        var query = $http.get(base_url + "get");
        query.success(function(data, status, headers, config) {
            console.log(data);
            $scope.response = data;
        });
        query.error(function(data, status, headers, config){
            console.log('fail');
            console.log(data);
        });

        var cars = {
            toyota: {
                from: 'japan',
                price: 100000
            },

            benz: {
                from: 'Germany',
                price: 500000
            }
        }
        //post和put的data接受任何Javascript对象(或者字符串),如果是对象则默认被转化为JSON字符串
        var post = $http.post(base_url + '/post/car', cars);
        //$http服务会视图对任何看起来像JSON的响应(以{},[])都执行从JSON字符串到Javascript对象的转化
        post.success(function(data, status, headers, config) {
            console.log(data);
        });

    });

 为了测试简单的restful,你可以用sts创建一个简单点 springboot项目,随便写几个get,post的API如下:

public class HelloController {

    @RequestMapping("/hello/{name}")
    public String hello(@PathVariable("name") String name, Model model) {
        model.addAttribute("name", name);
        return "hello";
    }

    @RequestMapping("/get")

    public @ResponseBody String hello(HttpServletResponse response) {
    //为了解决cross domain的问题,你不需要allow *,你的index.html并不是部署在和springboot所在的localhost:8080的服务器上
        response.addHeader("Access-Control-Allow-Origin", "*");
        return "{\"firstName\": \"John\", \"lastName\": \"Smith\", \"age\": 25}";
    }

    @RequestMapping(value="/post/car", method=RequestMethod.POST)
    public void post1(@RequestBody String body, HttpServletResponse response){
        System.out.println(body);
        response.addHeader("Access-Control-Allow-Origin", "*");
    }
}

 Promise API 

promise API的主要思想是,为异步世界带来我们在同步编程世界中所享有的那些便利之处,比如链式方法调用和错误处理。

在Promise API中,通常有两个角色:一个是控制未来任务的执行(延迟调用)占位符(promise),领一个则是依赖于未来任务的执行结果(保证承诺结果,resovle、reject)

AngularJS拥有非常轻量化的Promise API实现–$q服务,位数不少的AngularJS服务(主要是$http, $timeout等)相当依赖promise API风格,所以为了有效运行这些服务,需要熟悉$q. 
//此处省略$q的介绍,楼主暂时没看懂,而且觉得用处不太大,以后学了再补上。

Promise API与http的关系,http返回的承诺对象为then,这让我们能以如下方式覆盖回调注册

var query = $http.get(base_url + "get");
      query.then(function(data, status, headers, config) {
              console.log(data);
              $scope.response = data;
          },
          function(data, status, headers, config) {
              console.log('fail');
              console.log(data);
          }
      )

RESTful端点场提供CRUD操作,虽然这样的端点交互的代码通常很简单直接,不过写起来却很单调乏味。$resource服务允许我们消除重复代码,并让我们在更高的抽象级别上操作,用resources的形式去思考数据操纵,用方法调用来代替低级别的HTTTP调用。

$resource服务被分发在单独的文件中(angular-resource.js),属于专用模块(ngResource)。为了利用$resource服务,我们需要包含angular-resource.js文件,并在应用模块中声明对ngResource的模块依赖。
//HTML
    <div ng-controller="myController">
        <ul  >
            <li ng-repeat='user in users'>Name : {{user.name}}</li>
        </ul>
    </div>

//JS
     var base_url = 'http://localhost:8080/'
     angular.module('myapp1', ['ngResource'])
        .factory('Users', function($resource) {
            return $resource(base_url + 'get');
        })
        .controller('myController', function($scope, Users) {
            $scope.users = Users.query();
        })

 resourceAPI通过

resource()方法来使用$resources服务。这个方法可以接受三个参数。

  1. url(必选) 
    我们在这里传入一个包含所有参数的,用来定位资源的参数化URL字符串模板(参数以“:”为前缀)
//这里需要注意的是如果:之前的参数是空的(:id),那么URL中的这部分会被压缩成一个.符号。
//如果我们使用的服务器要求在URL中输入端口号,例如:http://localhost:8080/:id 则必须对:转义
//http://localhost\:8080/:id
$resource('/api/users/:id.:format',{
    format:'json',
    id: '123'
});
  1. paramDefaults(可选) 
    第二个参数包含了发送请求时URL重参数的默认值。对象中的键会与参数名进行匹配。如果我们传入了一个没有在URL中设置过的参数,那它会以普通的查询字符串的形式被发送。
例如,如果URL字符串具有/api/users/:id这样的签名,并且我们将默认值设置为{id:’123’, name:’Ari’},那么URL最终被转化成/api/users/123?name=Ari 
这里可以像上面一样硬编码一个值,也可以设置它从一个数据对象中读取动态值。 如果要设置动态之,需要在值之前加上@字符作为前缀 
{id:’@_id.$oid’}
  1. actions(可选) 
    动作对象是具有自定义动作,并且可以对默认的资源动作进行扩展的hash对象。 
    对象的键就是自定义动作的名字,而$http设置的对象的值会对URL中相应的参数进行替换。
$resource('/api/users/:id.:format', {
    format: 'json',
    id: '123'
}, {
    update: { methos: 'PUT' }
});
//action: {method:?, params:?, isArray:?, headers:?}
//isArray表示response是返回[]还是{}

 $resource创建异步方法

$scope.users = Users.query();
console.log($scope.users.length); //这里不会获得你期望的数组长度,而会返回0
//因此你必须使用异步方法去做。
Users.query(function(users){
    $scope.users = users;
    console.log(users.length);
})
$resource服务自动生成两套方法。其中一套方法会在类级别,另一套方法会在实例级别

 类级别

- Users.query(params, successcb, errorcb) : GET请求期望JSON数据返回,用于取得条目列表
- Users.get(params, successcb, errorcb): GET请求,期望JSON返回单个对象,用于取得单个条目
- Users.save(params,payloadData, successcb, errorcb): POST请求,请载荷中产生
- Users.delete(params, successcb, errrorcb):DELETE请求。

 params孕育我们为每个动作制定参数,它们将成为URL的一部分,或者作为查询字符串中的参数。

实例级别

var user = new Users({
    name : 'SuperHero'
});

user.$save();
user.$delete();

 自定义方法 

$resource工厂默认生成的方法对典型用例来说已经相当够用,但如果后端某些操作使用不同的HTTP动词(如PUT或者PATCH),那么在资源级别上添加自定义方法也相当容易。

相关推荐