이 기사의 예에서는 $http 비동기 백그라운드가 AngularJS에서 요청 매개변수를 얻을 수 없는 문제에 대한 솔루션을 설명합니다. 참고할 수 있도록 모든 사람과 공유하세요. 자세한 내용은 다음과 같습니다.
angular는 데이터를 비동기적으로 제출할 때 jQuery와 다른 요청 헤더 및 데이터 직렬화 방법을 사용하므로 일부 백그라운드 프로그램에서 데이터를 정상적으로 구문 분석할 수 없습니다.
원리 분석(온라인 분석):
AJAX 애플리케이션(XMLHttpRequests 사용)의 경우 서버에 대한 요청을 시작하는 전통적인 방법은 XMLHttpRequest 객체에 대한 참조를 얻고 요청을 시작하는 것입니다. , Get the response를 읽고, 상태 코드를 확인하고, 마지막으로 서버의 응답을 처리합니다. 전체 프로세스의 예는 다음과 같습니다.
var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if(xmlhttp.readystate == 4 && xmlhttp.status == 200) { var response = xmlhttp.responseText; }else if(xmlhttp.status == 400) { //或者可以是任何以4开头的状态码 //优雅地处理错误 } }; //建立连接 xmlhttp.open("GET", "http://myserver/api", true); //发起请求 xmlhttp.send();
이는 단순하고 일반적이며 자주 반복되는 작업에 매우 번거로운 작업입니다. 위 프로세스를 재사용하려면 캡슐화하거나 코드 라이브러리를 사용해야 합니다.
AngularJS XHR API는 일반적으로 Promise라고 알려진 인터페이스를 준수합니다. XHR은 비동기 호출 방식이므로 미래의 불확실한 시점에 서버의 응답이 반환될 것이다(즉시 반환되기를 바란다). Promise 인터페이스는 이 응답을 처리하는 방법을 지정하고 Promise 사용자가 이를 예측 가능한 방식으로 사용할 수 있도록 합니다.
예를 들어, 요청을 수락하는 데 사용되는 백그라운드 인터페이스가 /api/user 경로에 있다고 가정합니다. 이 인터페이스는 id 속성을 URL 매개변수로 받아들일 수 있습니다. , Angular를 사용합니다. 핵심 $http 서비스가 XHR 요청을 시작하는 방법의 예는 다음과 같습니다.
$http.get('api/user', {params: {id:'5'} }).success(function(data, status, headers, config) { //加载成功之后做一些事 }).error(function(data, status, headers, config) { //处理错误 });
jQuery를 사용하는 경우 사용자라면 AngularJS와 jQuery가 비동기 요청을 처리하는 데 매우 유사하다는 점을 알게 될 것입니다.
위 예시에서 사용된 $http.get 메소드는 AngularJS의 핵심 서비스인 $http에서 제공하는 수많은 단축 메소드 중 하나입니다. 마찬가지로, AngularJS를 사용하여 일부 POST 데이터가 포함된 동일한 URL로 POST 요청을 보내려면 다음과 같이 할 수 있습니다.
var postData = {text:'long blob of text'}; //下面这一行会被当成参数附加到URL后面,所以post请求最终会变成/api/user?id=5 var config = {params: {id: '5'}}; $http.post('api/user', postData, config ).success(function(data, status, headers, config) { //成功之后做一些事情 }).error(function(data, status, headers, config) { //处理错误 });
GET, HEAD, POST, DELETE, PUT, JSONP를 포함하여 가장 일반적으로 사용되는 요청 유형에 대해 유사한 단축 방법이 있습니다.
1. 요청 추가 구성
표준 요청 방법은 비교적 사용이 간단하지만 구성 가능성이 떨어지는 단점이 있습니다. 다음 사항을 구현하려는 경우 어려움에 직면하게 됩니다.
a. 요청에 인증 헤더를 추가합니다.
b. 캐시 처리 방식을 수정합니다.
c. 특별한 방법을 사용하여 전송된 요청을 변환하거나 수신된 응답을 변환합니다.
이러한 경우 선택적 구성 개체를 전달하여 요청을 심층적으로 구성할 수 있습니다. 이전 예에서는 구성 개체를 사용하여 선택적 URL 매개변수를 지정했습니다. 그러나 GET 및 POST 메소드에는 몇 가지 단축키가 있습니다. 이렇게 심층적으로 단순화한 후 메소드 호출의 예는 다음과 같습니다.
$http(config)
다음은 이전 메소드를 호출하기 위한 기본 의사코드 템플릿입니다. :
$http({ method: string, url: string, params: object, data: string or object, headers: object, transformRequest: function transform(data, headersGetter) or an array of functions, transformResponse: function transform(data, headersGetter) or an array of functions, cache: boolean or Cache object, timeout: number, withCredentials: boolean });
GET, POST 및 기타 단축 메소드는 메소드 매개변수를 자동으로 설정하므로 수동으로 설정할 필요가 없습니다. 구성 개체는 $http.get 및 $http.post의 마지막 매개변수로 전달되므로 이 매개변수는 모든 바로가기 메서드 내에서 사용할 수 있습니다. 구성 개체를 전달하여 전송된 요청을 수정할 수 있습니다. 구성 개체는 다음 키 값을 설정할 수 있습니다.
method: GET 또는 POST와 같은 HTTP 요청 유형을 나타내는 문자열입니다.
url: 요청된 절대 또는 상대 리소스 경로를 나타내는 URL 문자열입니다.
params: 키와 값이 모두 문자열(정확히는 맵)인 객체로, URL 매개변수로 변환해야 하는 키와 값을 나타냅니다. 예:
[{key1: 'value1', key2: 'value2'}]
은
?key1=value&key2=value2
timeout: 요청 시간이 초과될 때까지 기다려야 하는 시간(밀리초)입니다.
2.X-Requested-With: XMLHttpRequest
angular.module('MyApp', []). config(function($httpProvider) { //删除AngularJS默认的X-Request-With头 delete $httpProvider.default.headers.common['X-Requested-With']; //为所有GET请求设置DO NOT TRACK $httpProvider.default.headers.get['DNT'] = '1'; });
如果你只想对某些特定的请求设置请求头,但不把它们作为默认值,那么你可以把头信息作为配置对象的一部分传递给$http服务。同样的,自定义头信息也可以作为第二个参数的一部分传递给GET请求,第二个参数还可以同时接受URL参数。
$http.get('api/user', { //设置Authorization(授权)头。在真实的应用中,你需要到一个服务里面去获取auth令牌 headers: {'Authorization': 'Basic Qzsda231231'}, params: {id:5} }).success(function() {//处理成功的情况 });
三.缓存响应
对于HTTP GET请求,AngularJS提供了一个开箱即用的简单缓存机制。默认情况下它对所有请求类型都不可用,为了启用缓存,你需要做一些配置:
$http.get('http://server/myapi', { cache: true }).success(function() {//处理成功的情况});
这样就可以启用缓存,然后AngularJS将会缓存来自服务器的响应。下一次向同一个URL发送请求的时候,AngularJS将会返回缓存中的响应内容。缓存也是智能的,所以即使你向同一个URL发送多次模拟的请求,缓存也只会向服务器发送一个请求,而且在收到服务端的响应之后,响应的内容会被分发给所有请求。
但是,这样做有些不太实用,因为用户会先看到缓存的旧结果,然后看到新的结果突然出现。例如,当用户即将点击一条数据时,它可能会突然发生变化。
注意,从本质上来说,响应(即使是从缓存中读取的)依然是异步的。换句话说,在第一次发出请求的时候,你应该使用处理异步请求的方式来编码。
四.转换请求和响应
对于所有通过$http服务发出的请求和收到的响应来说,AngularJS都会进行一些基本的转换,包括如下内容。
1.转换请求
如果请求的配置对象属性中包含JS对象,那么就把这个对象序列化成JSON格式。
2.转换响应
如果检测到了XSRF(Cross Site Request Forgery的缩写,意为跨站请求伪造,这是跨站脚本攻击的一种方式)前缀,则直接丢弃。如果检测到了JSON响应,则使用JSON解析器对它进行反序列化。
如果你不需要其中的某些转换,或者想自已进行转换,可以在配置项里面传入自已的函数。这些函数会获取HTTP的request/response体以及协议头信息,然后输出序列化、修改之后的版本。可以使用transformLRequest和transformResponse作为key来配置这些转换函数,而这两个函数在模块的config函数中是用$httpProvider服务来配置的。
我们什么时候需要使用这些东西呢?假设我们有一个服务,它更适合用jQuery的方式来操作。POST数据使用key1=val1&key2=val2(也就是字符串)形式来代替{key1:val1, key2:val2}JSON格式。我们可以在每个请求中来进行这种转换,也可以添加一个独立transformRequest调用,对于当前这个例子来说,我们打算添加一个通用的transformRequest,这样所有发出的请求都会进行这种从JSON到字符串的转换。下面就是实现方式:
var module = angular.module('myApp'); module.config(function($httpProvider) { $httpProvider.defaults.transformRequest = function(data) { //使用jQuery的param方法把JSON数据转换成字符串形式 return $.param(data); }; });
实列配置:
在使用中发现后台程序还是无法解析angular提交的数据,对比后发现头部缺少‘X-Requested-With'项
所以在配置中加入:
复制代码代码如下:
$httpProvider.defaults.headers.post['X-Requested-With'] = 'XMLHttpRequest'
下面贴入测试时的部分配置代码:
angular.module('app', [ 'ngAnimate', 'ngCookies', 'ngResource', 'ngRoute', 'ngSanitize', 'ngTouch' ],function ($httpProvider) { // 头部配置 $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8'; $httpProvider.defaults.headers.post['Accept'] = 'application/json, text/javascript, */*; q=0.01'; $httpProvider.defaults.headers.post['X-Requested-With'] = 'XMLHttpRequest'; /** * 重写angular的param方法,使angular使用jquery一样的数据序列化方式 The workhorse; converts an object to x-www-form-urlencoded serialization. * @param {Object} obj * @return {String} */ var param = function (obj) { var query = '', name, value, fullSubName, subName, subValue, innerObj, i; for (name in obj) { value = obj[name]; if (value instanceof Array) { for (i = 0; i < value.length; ++i) { subValue = value[i]; fullSubName = name + '[' + i + ']'; innerObj = {}; innerObj[fullSubName] = subValue; query += param(innerObj) + '&'; } } else if (value instanceof Object) { for (subName in value) { subValue = value[subName]; fullSubName = name + '[' + subName + ']'; innerObj = {}; innerObj[fullSubName] = subValue; query += param(innerObj) + '&'; } } else if (value !== undefined && value !== null) query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&'; } return query.length ? query.substr(0, query.length - 1) : query; }; // Override $http service's default transformRequest $httpProvider.defaults.transformRequest = [function (data) { return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data; }]; }).config(function ($routeProvider) { $routeProvider .when('/', { templateUrl: 'views/main.html', controller: 'MainCtrl' }) .when('/about', { templateUrl: 'views/about.html', controller: 'AboutCtrl' }) .otherwise({ redirectTo: '/' }); });
希望本文所述对大家AngularJS程序设计有所帮助。