我有一些旧代码通过 jQuery's post method 发出 AJAX POST 请求,看起来像这样:
$.post("/foo/bar", requestData,
function(responseData)
{
//do stuff with response
}
requestData
只是一个带有一些基本字符串属性的 javascript 对象。
我正在将我们的东西转移到使用 Angular 的过程中,我想用 $http.post 替换这个调用。我想出了以下内容:
$http.post("/foo/bar", requestData).success(
function(responseData) {
//do stuff with response
}
});
当我这样做时,我收到了来自服务器的 500 错误响应。使用 Firebug,我发现这发送了这样的请求正文:
{"param1":"value1","param2":"value2","param3":"value3"}
成功的 jQuery $.post
发送正文如下:
param1=value1¶m2=value2¶m3=value3
我要访问的端点是请求参数而不是 JSON。所以,我的问题是无论如何要告诉 $http.post
将 javascript 对象作为请求参数而不是 JSON 发送?是的,我知道我可以自己从对象构造字符串,但我想知道 Angular 是否为此提供了开箱即用的东西。
我认为 params
配置参数在这里不起作用,因为它将字符串添加到 url 而不是正文,但添加到 Infeligo 建议的内容是默认转换的全局覆盖示例(使用 jQuery param作为将数据转换为参数字符串的示例)。
设置全局 transformRequest 函数:
var app = angular.module('myApp');
app.config(function ($httpProvider) {
$httpProvider.defaults.transformRequest = function(data){
if (data === undefined) {
return data;
}
return $.param(data);
}
});
这样,所有对 $http.post 的调用都会自动将正文转换为 jQuery $.post
调用使用的相同参数格式。
请注意,您可能还希望在每次调用或全局设置 Content-Type 标头,如下所示:
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
每次调用的示例非全局 transformRequest:
var transform = function(data){
return $.param(data);
}
$http.post("/foo/bar", requestData, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
transformRequest: transform
}).success(function(responseData) {
//do stuff with response
});
如果使用 Angular >= 1.4,这是我发现的最干净的解决方案,它不依赖于任何自定义或外部:
angular.module('yourModule')
.config(function ($httpProvider, $httpParamSerializerJQLikeProvider){
$httpProvider.defaults.transformRequest.unshift($httpParamSerializerJQLikeProvider.$get());
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
});
然后您可以在应用程序的任何位置执行此操作:
$http({
method: 'POST',
url: '/requesturl',
data: {
param1: 'value1',
param2: 'value2'
}
});
并且它将正确地将数据序列化为 param1=value1¶m2=value2
并将其发送到 /requesturl
并带有 application/x-www-form-urlencoded; charset=utf-8
Content-Type 标头,正如端点上的 POST 请求通常所期望的那样。
来自 AngularJS 文档:
params – {Object.} – 字符串或对象的映射,将在 url 之后转换为 ?key1=value1&key2=value2。如果值不是字符串,它将被 JSON 化。
因此,提供字符串作为参数。如果您不希望那样,请使用转换。同样,从文档中:
要在本地覆盖这些转换,请将转换函数指定为配置对象的 transformRequest 和/或 transformResponse 属性。要全局覆盖默认转换,请覆盖 $httpProvider 的 $httpProvider.defaults.transformRequest 和 $httpProvider.defaults.transformResponse 属性。
有关详细信息,请参阅 documentation。
使用 jQuery 的 $.param
函数序列化 requestData 中的 JSON 数据。
简而言之,使用与您类似的代码:
$http.post("/foo/bar",
$.param(requestData),
{
headers:
{
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
}
).success(
function(responseData) {
//do stuff with response
}
});
要使用它,您必须在页面中包含 jQuery 以及 AngularJS。
请注意,从 Angular 1.4 开始,您可以在不使用 jQuery 的情况下序列化表单数据。
在 app.js 中:
module.run(function($http, $httpParamSerializerJQLike) {
$http.defaults.transformRequest.unshift($httpParamSerializerJQLike);
});
然后在你的控制器中:
$http({
method: 'POST',
url: myUrl',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: myData
});
这可能有点麻烦,但我避免了这个问题,并将 json 转换为服务器端的 PHP POST 数组:
$_POST = json_decode(file_get_contents('php://input'), true);
我在设置自定义 http 身份验证时也遇到了问题,因为 $resource 缓存了请求。
要使其正常工作,您必须通过执行此操作来覆盖现有的标头
var transformRequest = function(data, headersGetter){
var headers = headersGetter();
headers['Authorization'] = 'WSSE profile="UsernameToken"';
headers['X-WSSE'] = 'UsernameToken ' + nonce
headers['Content-Type'] = 'application/json';
};
return $resource(
url,
{
},
{
query: {
method: 'POST',
url: apiURL + '/profile',
transformRequest: transformRequest,
params: {userId: '@userId'}
},
}
);
我希望我能帮助别人。我花了 3 天时间才弄清楚这一点。
修改默认标题:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";
然后使用 JQuery 的 $.param
方法:
var payload = $.param({key: value});
$http.post(targetURL, payload);
.controller('pieChartController', ['$scope', '$http', '$httpParamSerializerJQLike', function($scope, $http, $httpParamSerializerJQLike) {
var data = {
TimeStamp : "2016-04-25 12:50:00"
};
$http({
method: 'POST',
url: 'serverutilizationreport',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: $httpParamSerializerJQLike(data),
}).success(function () {});
}
]);
快速调整 - 对于那些在 transformRequest 函数的全局配置方面遇到问题的人,这是我用来摆脱 Cannot read property 'jquery' of undefined
错误的代码段:
$httpProvider.defaults.transformRequest = function(data) {
return data != undefined ? $.param(data) : null;
}
您也可以在不更改服务器代码、更改 $http.post
调用中的标头并按常规方式使用 $_POST
的情况下解决此问题。此处解释:http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/
我发现很多次有问题的行为。我从 express(没有类型)和 bodyParser(使用 dt~body-parser 类型)中使用它。
我没有尝试上传文件,而是简单地解释在帖子字符串中给出的 JSON。
request.body
只是一个空 json ({}
)。
经过大量调查终于这对我有用:
import { json } from 'body-parser';
...
app.use(json()); <-- should be defined before the first POST handler!
在客户端的请求字符串中提供 application/json
内容类型可能也很重要。
AngularJS v1.4.8 + (v1.5.0) 的语法
$http.post(url, data, config)
.then(
function (response) {
// success callback
},
function (response) {
// failure callback
}
);
例如:
var url = "http://example.com";
var data = {
"param1": "value1",
"param2": "value2",
"param3": "value3"
};
var config = {
headers: {
'Content-Type': "application/json"
}
};
$http.post(url, data, config)
.then(
function (response) {
// success callback
},
function (response) {
// failure callback
}
);
$httpProvider.defaults
全局设置时,它不起作用,有什么线索吗?Cannot read property "jquery" of undefined.
如何解决此问题? PS。每次调用转换都有效。