angularjs http 请求 php 无数据解决办法

虽然angularjs自带http请求,但是当它的后台为php时,我们往往拿不到想要的数据(相同的请求用jQuery能正确返回结果)。其实这是因为angularjs默认的请求方式不适合php接收而已。因此我们需要修改或者使用其他的请求方式来实现与后台的交互。

$http默认请求头信息

$http服务将会给所有请求自动创建HTTP头。这个默认设置能完全的通过访问$httpProvider.defaults.headers配置对象配置。目前包含默:

  $httpProvider.defaults.headers.common
        //-- Accept:application/json,text/plain
  $httpProvider.defaults.headers.post
        //-- Content-Type:application/json
  $httpProvider.defaults.headers.put
        //-- Content-Type:application/json

解决方法

以下案例均通过wampserver环境下的php后台请求测试,如果非此类环境有可能拿不到想要的结果,请自行封装其他方法解决。

以下案例的实现均需要有正常的php开发环境来支持,假如我们有这样一个ajax.php文件:

<?php
header('Content-type:text/html;charset=utf-8');
if ($_GET) {
    $msg = ['name' => $_GET['name'], 'type' => '这是get请求'];
    echo json_encode($msg);
    exit();
}
if ($_POST) {
    $msg = ['name' => $_POST['name'], 'type' => '这是post请求'];
    echo json_encode($msg);
    exit();
}
$msg = ['type' => '这是其他请求'];
echo json_encode($msg);

方法一:封装自定义httpService服务(推荐做法)

利用$httpParamSerializerJQLike和Content-Type设置来封装自定义服务,可以友好解决这个问题,而且它可以像jQuery那样发请求(注意自定义服务的调用方式,如果不明白什么是服务,可以参考angularjs service 自定义服务 或者 angularjs factory (工厂服务))。

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8">
    <title>angularjs service</title>
    <meta name="author" content="loushengyue">
</head>
<body>

<div ng-app="app" ng-controller="ctrl">
    <h1>请按F12查看控制台的console面板</h1>
</div>

<script src="https://cdn.bootcss.com/angular.js/1.6.9/angular.min.js"></script>
<script>
    angular.module('app', [])
            .controller('ctrl', ['$scope', 'httpService', function ($scope, httpService) {
                var option = {
                    type: 'post',
                    url: './ajax.php',
                    data: {
                        name: 'loushengyue'
                    }
                };
                httpService.request(option).then(function (res) {
                    console.log(res);
                }, function (error) {
                    console.log(error);
                })
            }])
            .service('httpService', ['$http', '$q', '$httpParamSerializerJQLike',
                function ($http, $q, $httpParamSerializerJQLike) {
                    //$httpParamSerializerJQLike表示它可以像jquery那样序列化数据
                    this.request = function (option) {
                        if (!option || !option.url) {
                            throw new Error('option or option.url is undefind.');
                        }
                        var def = $q.defer(), _method,
                                _data = option.data ? option.data : {};
                        option.method = option.method ? option.method : (option.type ? option.type : 'get');
                        _method = angular.uppercase(option.method);
                        if (_method === 'GET' && !option.params) {
                            option.params = _data; //使get请求支持data传参
                        }
                        if (_method === 'POST') {
                            var _config = {
                                headers: {"Content-Type": "application/x-www-form-urlencoded"}
                            };
                            option.data = $httpParamSerializerJQLike(_data);
                            angular.merge(option, _config);//合并请求参数使post请求类似jquery一样
                        }
                        $http(option).then(function (res) {
                            def.resolve(res.data)
                        }, function (error) {
                            def.reject(error)
                        });
                        return def.promise;
                    };
                    return this;
                }])
</script>
</body>
</html>

方法二: 修改$httpProvider配制

这是一种各大博客网友推荐的一种做法,它能够一次性配制所有的$http内置服务的post请求方式(不过这种配制是有漏洞的,它不支持复杂参数的传递)。

<div ng-app="app" ng-controller="ctrl">
    <h1>请按F12查看控制台的console面板</h1>
    <div>
        <button ng-click="getRequest()">get request test</button>
        <br>
        <button ng-click="postRequest()">post request test</button>
    </div>
</div>

<script src="https://cdn.bootcss.com/angular.js/1.6.9/angular.min.js"></script>
<script>
    angular.module('app', [])
            .config(['$httpProvider', function ($httpProvider) {
                $httpProvider.defaults.transformRequest = function (data) {
                    var arr = [];
                    angular.forEach(data, function (val, key) {
                        arr.push(encodeURIComponent(key) + '=' + encodeURIComponent(val));
                    });
                    return arr.join('&');
                };
                //通过下面这一行你能看到你$http的默认配置信息
                console.log($httpProvider.defaults.headers);//请自行删除本行
                $httpProvider.defaults.headers = {
                    post: {
                        'Content-Type': 'application/x-www-form-urlencoded'
                    }
                }
            }])
            .controller('ctrl', ['$scope', '$http', function ($scope, $http) {
                $scope.getRequest = function () {
                    $http({
                        method: 'get',//切记这里是method!!jQuery用的是type
                        url: './ajax.php?name=loushengyue&age=30'
                        //angularjs的get请求没有data传参,需要拼接url或者用params对象
                    }).then(function (res) {
                        console.log(res.data);
                        alert('get success')
                    })
                };
                $scope.postRequest = function () {
                    $http({
                        method: 'post', //切记这里是method!!jQuery用的是type
                        url: './ajax.php',
                        data: {
                            name: 'loushengyue',
                            age: 30,
                            sex: 'male'
                        }
                    }).then(function (res) {
                        console.log(res.data);
                        alert('post success');
                    })
                };
            }])
</script>

方法三:修改$http配置

<div ng-app="app" ng-controller="ctrl">
    <h1>请按F12查看控制台的console面板</h1>
    <div>
        <button ng-click="getRequest()">get request test</button>
        <br>
        <button ng-click="postRequest()">post request test</button>
    </div>
</div>

<script src="https://cdn.bootcss.com/angular.js/1.6.9/angular.min.js"></script>
<script>
    angular.module('app', [])
            .controller('ctrl', ['$scope', '$http', '$httpParamSerializerJQLike',
                function ($scope, $http, $httpParamSerializerJQLike) {
                    $scope.getRequest = function () {
                        $http({
                            method: 'get',//切记这里是method!!jQuery用的是type
                            url: './ajax.php',
                            params: {
                                name: 'test',
                                age: 18
                            }
                            //angularjs的get请求没有data传参,需要拼接url或者用params对象
                        }).then(function (res) {
                            console.log(res.data);
                            alert('get success')
                        })
                    };
                    $scope.postRequest = function () {
                        $http({
                            method: 'post', //切记这里是method!!jQuery用的是type
                            url: './ajax.php',
                            data: $httpParamSerializerJQLike({
                                name: 'loushengyue',
                                age: 30,
                                sex: 'male'
                            }),
                            headers: {
                                'Content-Type': 'application/x-www-form-urlencoded'
                            }
                        }).then(function (res) {
                            console.log(res.data);
                            alert('post success');
                        })
                    };
                }])
</script>

$httpParamSerializerJQLike部分原码展示

function jQueryLikeParamSerializer(params) {
        if (!params) return '';
        var parts = [];
        serialize(params, '', true);
        return parts.join('&');

        function serialize(toSerialize, prefix, topLevel) {
            if (toSerialize === null || isUndefined(toSerialize)) return;
            if (isArray(toSerialize)) {
                forEach(toSerialize, function (value, index) {
                    serialize(value, prefix + '[' + (isObject(value) ? index : '') + ']');
                });
            } else if (isObject(toSerialize) && !isDate(toSerialize)) {
                forEachSorted(toSerialize, function (value, key) {
                    serialize(value, prefix +
                            (topLevel ? '' : '[') +
                            key +
                            (topLevel ? '' : ']'));
                });
            } else {
                parts.push(encodeUriQuery(prefix) + '=' + encodeUriQuery(serializeValue(toSerialize)));
            }
        }
    }

    function encodeUriQuery(val, pctEncodeSpaces) {
        return encodeURIComponent(val).
        replace(/%40/gi, '@').
        replace(/%3A/gi, ':').
        replace(/%24/g, '$').
        replace(/%2C/gi, ',').
        replace(/%3B/gi, ';').
        replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
    }

      function serializeValue(v) {
        if (isObject(v)) {
            return isDate(v) ? v.toISOString() : toJson(v);
        }
        return v;
    }

猜你喜欢

转载自blog.csdn.net/weixin_41424247/article/details/79826192
今日推荐