本网站只能被运行在支持JavaScript脚本的环境中

第九节 向服务器端发出请求

服务器端脚本文件(Node.js+Express版)

var express = require('express');
url=require("url");
querystring=require('querystring'); 
path=require('path');
var app = express();
app.configure(function(){
    app.use(express.methodOverride()); 
    app.use(express.bodyParser());
    app.use(express.static(__dirname));
    app.use(app.router);   
    app.all('/*',function (req, res) {
        console.log("url:"+url.parse(req.url).href);      
        console.log("method:"+req.method);   
        console.log("querystring:");  
        console.log(querystring.parse(url.parse(req.url).query));
        res.send("success");
    });  
});
var webServer =app.listen(8080);

当服务器端接收到客户端任何请求时,都会将请求信息输出在控制台中。

基本

<!doctype html>
<html ng-app="myApp"> 
<head>
<title>Node app</title>
<script src="angular.js"></script>
<script>
angular.module('myApp', []) 
.controller('SampleController',function($scope,$http){
    var uri='ajax/test';
    var param = {params: {hoge: 'HOGE', apple: '苹果'}};
    $http.get(uri,param)
    .success(function(data,status,headers,config){
        log('success',data,status,headers,config);
    })
    .error(function(data,status,headers,config){
        log('error',data,status,headers,config);
    });
    function log(type, data, status, headers, config) {
        $scope.response = {
            type: type,
            data: data,
            status: status,
            headers: headers,
            config: config
        };
    }
});
</script>
</head>
<body ng-controller="SampleController">
    <pre>{{response | json}}</pre>
</body>
</html>

启动Node.js服务器后,访问http://localhost:8080/sample.html页面。

显示结果

服务器端输出结果

向服务器端发出请求时,需要在服务或控制器中注入$http指令。

调用$http的用于向服务器端发出请求的方法(与HTTP方法相对应)。

当服务器端返回JSON格式字符串时,自动将其进行解析。

请求REST资源

<!doctype html>
<html ng-app="myApp"> 
<head>
<title>Node app</title>
<script src="angular.js"></script>
<script src="angular-route.min.js"></script>
<script>
angular.module('myApp', ['ngResource']) 
.controller('SampleController',function($resource,$q){
    var Res=$resource('ajax/res');
    Res.get().$promise.then(function(){
        return Res.save().$promise;
    })
    .then(function(){
        return Res.delete().$promise;
    });
});
</script>
</head>
<body ng-controller="SampleController">
</body>
</html>

服务器端控制台输出:

首先引用angular-route.js或angular-route.min.js脚本文件并加载ngResource模块。

执行$resource函数并在参数中指定URL,该函数返回一个对象,可以使用该对象的get、save、delete等方法发出各种基本的REST请求。

这些方法均返回一个对象,该对象的$promise属性值为一个promise对象,可以通过该对象的使用在第一个请求响应返回后发出第二个请求。

用于发出请求的方法所对应的HTTP方法

方法名 对应的HTTP方法 服务器端返回数据类型
get GET 对象
save POST 对象
query GET 数组
remove DELETE 对象
delete DELETE 对象

各HTTP方法的参数

GET请求

var Res=$resource('ajax/res');
Res.action([parameters], [success], [error])
例:
Res.get({a: 10}, function() {/*success*/}, function() {/*error*/});

非GET请求

var Res=$resource('ajax/res');
Res.action([parameters], postData, [success], [error]);
例:
Res.save({a: 11}, {b: 'Bbb'}, function() {/*success*/}, function() {/*error*/});

在请求路径中使用参数

<!doctype html>
<html ng-app="myApp"> 
<head>
<title>Node app</title>
<script src="angular.js"></script>
<script src="angular-resource.min.js"></script>
<script>
angular.module('myApp', ['ngResource']) 
.controller('SampleController',function($resource,$q){
    var Res = $resource('ajax/res/:hoge/:apple/:piyo', {hoge: 'Hoge'});

    Res.get({apple: '苹果'});
});
</script>
</head>
<body ng-controller="SampleController">
</body>
</html>

服务器端控制台输出

如果在$resource函数的URL中以:<参数名>的形式书写路径,在发出请求时AngularJS将自动将参数值填入。

可以在$resource函数的第二参数中,指定参数的默认值。

虽然定义了参数,如果请求时参数值未指定,请求的URL中将自动去除该参数(例如本例中的piyo)。

在请求数据中填入参数

<!doctype html>
<html ng-app="myApp"> 
<head>
<title>Node app</title>
<script src="angular.js"></script>
<script src="angular-resource.min.js"></script>
<script>
angular.module('myApp', ['ngResource']) 
.controller('SampleController',function($resource,$q){
    var Res = $resource('ajax/res/:hoge/:apple', {hoge: '@Hoge',apple: '@apple'});
    var param={hoge:'HOGE'};
    var postData={hoge:'Hoge',apple:'APPLE'};
    Res.save(param,postData);
});
</script>
</head>
<body ng-controller="SampleController">
</body>
</html>

服务器端代码

var express = require('express');
url=require("url");
querystring=require('querystring'); 
path=require('path');
var app = express();
app.configure(function(){
    app.use(express.methodOverride()); 
    app.use(express.bodyParser());
    app.use(express.static(__dirname));
    app.use(app.router);   
    app.all('/*',function (req, res) {
        console.log("url:"+url.parse(req.url).href);      
        console.log("method:"+req.method);   
        console.log("querystring:");  
        console.log(querystring.parse(url.parse(req.url).query));
        console.log(req.body);
        res.send("success");
    }); 
});
var webServer =app.listen(8080);

服务器端控制台输出

如果在参数的默认值的开头书写@,该值将从请求数据中获取。

但是,如果该值被另行指定的话,以另行指定的值为准。

该方法主要用于非GET方法。

在第一个请求得到响应后继续使用Res对象

服务器端代码

var express = require('express');
url=require("url");
querystring=require('querystring'); 
path=require('path');
var  hits = require('./routes/hits');
var app = express();
app.configure(function(){
    app.use(express.methodOverride()); 
    app.use(express.bodyParser());
    app.use(express.static(__dirname));
    app.use(app.router);   
    app.all('/*',function (req, res) {
        console.log("url:"+url.parse(req.url).href);      
        console.log("method:"+req.method);   
        console.log("querystring:");  
        console.log(querystring.parse(url.parse(req.url).query));
        console.log("body:");
        console.log(req.body);
        res.writeHead(200,{'Content-Type':'application/json'});
        res.end('{"message":"success"}');
    });  
});
var webServer =app.listen(8080);

页面代码

<!doctype html>
<html ng-app="myApp"> 
<head>
<title>Node app</title>
<script src="angular.js"></script>
<script src="angular-resource.min.js"></script>
<script>
angular.module('myApp', ['ngResource']) 
.controller('SampleController',function($resource,$q){
    var Res = $resource('ajax/res');
    Res.get(function(res) {
        console.log('(res instanceof Res) = ' + (res instanceof Res));
        console.log('res.message = ' + res.message);
        res.hoge = 'HOGE';
        res.$save();
    });
});
</script>
</head>
<body ng-controller="SampleController">
</body>
</html>

浏览器中控制台输出

(res instanceof Res) = true
res.message = success

服务器端控制台输出

在Res.get方法成功返回之后,在回调函数中可以取得该Res对象。

在返回的Res对象中保存了服务器端返回的数据。

可以继续使用Res对象的$save等方法向服务器端发出请求。

如果设置该Res对象的属性值,该属性值可以作为提交数据提交到服务器端。

也就是说,提交之后在回调函数中可以获取发出请求的Res对象。

angular.module('myApp', ['ngResource']) 
.controller('SampleController',function($resource,$q){
   var Res = $resource('ajax/res');
    var a;
    var b = Res.get(function(res) {
        a = res;
    });
    b.$promise.then(function() {
        console.log(a === b); // true
    });
});

Res.get()方法的返回值b为执行了请求之后立即创建的空对象。

待服务器端返回响应之后,在该对象中填入服务器端响应数据。

Res对象的请求方法的参数

instance.$action([parameters], [success], [error]);
例:
res.$save({a: 11}, function() {/*success*/}, function() {/*error*/});

自定义请求方法

angular.module('myApp', ['ngResource']) 
.controller('SampleController',function($resource,$q){
   var Res = $resource('ajax/res',{},{myAction:{method:'PUT'}});
   Res.myAction(function(res) {
        res.$myAction();
    });
});

服务器端控制台输出

可以在$resource函数的第三个参数值中自定义请求方法。

定义拦截器

服务器端代码

var express = require('express');
url=require("url");
querystring=require('querystring'); 
path=require('path');
var  hits = require('./routes/hits');
var app = express();
app.configure(function(){
    app.use(express.methodOverride()); 
    app.use(express.bodyParser());
    app.use(express.static(__dirname));
    app.use(app.router);   
    app.all('/ajax/success',function (req, res) {
        console.log("url:"+url.parse(req.url).href);      
        console.log("method:"+req.method);   
        console.log("querystring:");  
        console.log(querystring.parse(url.parse(req.url).query));
        console.log("body:");
        console.log(req.body);
        res.writeHead(200,{'Content-Type':'application/json'});
        res.end('{"message":"success"}');
    });
});
var webServer =app.listen(8080);

客户端页面

<!doctype html>
<html ng-app="myApp"> 
<head>
<title>Node app</title>
<script src="angular.js"></script>
<script>
angular.module('myApp', []) 
.config(function($httpProvider){
    $httpProvider.interceptors.push(function($q) {
        return{
            request:function(config){
                console.log('request:'+config.url);
                return config||$q.when(config);
            },
            requestError:function(rejection){
                console.log('requestError');
                return $q.reject(rejection);
            },
            response:function(response){
                console.log('response:'+response.config.url);
                return response||$q.when(response);
            },
            responseError:function(rejection){
                console.log('responseError:'+rejection.config.url);
                return $q.reject(rejection);
            }
        };
    });
})
.controller('SampleController',function($http,$q){
    $q.when($http.get('ajax/success'))
    .then(success, error)
    .then(function() {
        return $http.get('ajax/error');
    })
    .then(success, error);

    function success() {
        console.log('success');
    }

    function error() {
        console.log('error');
    }
});
</script>
</head>
<body ng-controller="SampleController">
</body>
</html>

浏览器控制台输出

在$httpProvider.interceptors中push拦截器函数。

在拦截器中可以定义以下四种函数:

  • request:定义在请求前执行的处理。
  • requestError:定义请求失败时执行的处理。
  • response:定义接收到服务器端响应后立即执行的处理。
  • responseError:定义接受到服务器端响应错误后立即执行的处理。