AngularJS - $http.post 发送请求参数而不是 JSON 的任何方式?

IT技术 javascript jquery post angularjs
2021-01-14 07:18:48

我有一些旧代码通过jQuery 的 post 方法发出 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&param2=value2&param3=value3

我正在访问的端点需要请求参数而不是 JSON。所以,我的问题是无论如何要告诉$http.post将 javascript 对象作为请求参数而不是 JSON 发送?是的,我知道我可以自己从对象构造字符串,但我想知道 Angular 是否提供了任何开箱即用的功能。

6个回答

我认为paramsconfig 参数在这里不起作用,因为它将字符串添加到 url 而不是正文,但要添加到 Infeligo 建议的内容,这里是默认转换的全局覆盖示例(使用 jQuery参数作为转换的示例)数据到参数字符串)。

设置全局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';

每次调用的非全局转换请求示例:

    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
    });
非全局每次调用方法对我来说效果很好,但是当尝试通过 全局设置时$httpProvider.defaults,它不起作用,关于这个的任何线索?
2021-03-14 07:18:48
我想知道除了具有 transformRequest 函数之外是否还有其他东西,但听起来没有。感谢您了解 jQuery param 函数。
2021-03-18 07:18:48
WRT 全局配置它,我也有问题。当我尝试使用此处给出的代码段执行此操作时,出现错误Cannot read property "jquery" of undefined.如何解决此问题?附注。每次调用转换工作。
2021-03-21 07:18:48
从 Angular 1.4 开始,您可以使用 $httpParamSerializer 而不是 jQuery docs.angularjs.org/api/ng/service/$httpParamSerializer
2021-04-02 07:18:48
@kshep92 发生的事情是在没有数据的请求上调用了 transformRequest 函数,因此未定义“数据”。我在'return $.param(data);'之前添加了一个守卫。将此作为第一行插入到 transformRequest 函数中:'if (data === undefined) return data;' 请参阅我对答案所做的编辑。
2021-04-05 07:18:48

如果使用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&param2=value2并将其/requesturlapplication/x-www-form-urlencoded; charset=utf-8Content-Type 标头一起发送到端点上的 POST 请求通常是预期的。

来自 AngularJS 文档:

params – {Object.} – 字符串或对象的映射,将在 url 之后转换为 ?key1=value1&key2=value2。如果值不是 string,它将被 JSONified。

因此,提供字符串作为参数。如果您不想要那样,请使用转换。再次,从文档中:

要在本地覆盖这些转换,请将转换函数指定为配置对象的 transformRequest 和/或 transformResponse 属性。要全局覆盖默认转换,请覆盖 $httpProvider 的 $httpProvider.defaults.transformRequest 和 $httpProvider.defaults.transformResponse 属性。

有关更多详细信息,请参阅文档

我在文档中看到了参数,就像 Gloopy 提到的那样,我需要它在正文中,而不是在 URL 上。我想知道是否有一些选项或我缺少的东西来做参数而不是 JSON,但听起来我只需要使用 transformRequest 属性。
2021-04-03 07:18:48

使用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
});
我刚刚实现了这个,它解决了我在 post 中遇到的问题,但这也改变了补丁的工作方式,似乎已经破坏了我对 $http.patch() 的所有使用。
2021-03-12 07:18:48
这个答案很棒。它解决了来自 Angular 的 Post 的两个主要问题。必须正确设置标头,并且必须序列化 json 数据。如果您不需要 IE8 支持,请使用 1.4+ 或更高版本。
2021-03-20 07:18:48