Angular $http 将数据附加为对象

Angular $http attach data as object

我正在尝试使用 angularjs 从 soundcloud API 获取曲目列表。
我要发送的参数是:
1)client_id(字符串)
2)持续时间(具有两个属性的对象)。

代码如下:

    var CLIENT_ID = 'a81f01ef5d0036415431e8be76c8db0e';
    var TRACKS_URL = 'https://api.soundcloud.com/tracks.json';

    var app = angular.module('soundcloud', []);

    app.controller('tracksController', function ($scope, $http) {

        $http({
            url: 'https://api.soundcloud.com/tracks.json',
            method: 'GET',
            data: {
                client_id: CLIENT_ID,
                duration: { // in milliseconds
                    from: 300000,
                    to: 400000
                }
            }
        })
            .success(function (data) {
                $scope.trackList = data;
            })
            .error(function () { alert('error'); });
    });

当我在浏览器的调试器中检查请求时,这些参数根本无法识别。

我尝试使用 'params' 而不是 'data',但这样它会将 'duration' 对象变成 json --> 然后我得到状态 500 作为响应.
当我只在参数中发送 client_id 时,它工作正常,因为没有对象,只有字符串。

jQuery 的 ajax 方法工作正常:https://jsfiddle.net/oacwz1up/3/

我该怎么办?如何才能正常发送参数?
请帮助!谢谢!

如果您查看 $http documentation,它会根据要求应用默认转换 $http.defaults.transformRequest 并且如所述将执行以下操作(如您所见):

If the data property of the request configuration object contains an object, serialize it into JSON format.

您需要做的是通过指定您自己的 transformRequest 对象来覆盖此函数。

function appendTransform(defaults, transform) {

  // We can't guarantee that the default transformation is an array
  defaults = angular.isArray(defaults) ? defaults : [defaults];

  // Append the new transformation to the defaults
  return defaults.concat(transform);
}

  $http({
      url: '...',
      method: 'GET',
      transformResponse: appendTransform($http.defaults.transformResponse, function(value) {
        return doTransform(value);
      })
  });

您需要找到一种方法来获得与 jQuery 相同的语法,即:

https://api.soundcloud.com/tracks.json?client_id=a81f01ef5d0036415431e8be76c8db0e&duration[from]=200000&duration[to]=205000

使用条件是一个对象并手动生成您的字符串。应该不难。

这很奇怪 API - 我不知道为什么他们不做 "duration_from" 之类的事情而不是要求持续时间 [from] - 按照建议你当然可以转换请求,但是如果这只是一个关闭,您也可以尝试使用 url 转义值对 []:

进行简单的硬编码
 var dataToSend = {
     client_id: 'a81f01ef5d0036415431e8be76c8db0e',
     'duration%5Bfrom%5D': 200000,
     'duration%5Bto%5D': 205000
 }; 

发生这种情况是因为 Angular 序列化请求参数的方式与 JQuery 不同。

Angular 1.4 将解决这个问题,在 $http config object (and on $httpProvider.defaults 上引入 paramSerializer 属性)。这可用于任意序列化请求参数(针对所有或特定请求)。

请注意,自 v1.4.0-rc.0.

以来,该功能 可用

除了默认的序列化器(将对象转换为 JSON 字符串)之外,还有一个额外的内置序列化器可以模拟 JQuery 的 param()$httpParamSerializerJQLike .

你可以这样使用它:

$http.get(<API_URL>, {
  params: {...},
  paramSerializer: '$httpParamSerializerJQLike'
});

另见 short demo


如果您使用的是旧版本 Angular,您可以执行以下操作之一:

  1. 自己构造整个 URL(包括查询字符串)(可能使用 $http 请求 interceptor 自动将其应用于所有请求)。

  2. 将参数保持 平坦 格式,这将导致 Angular 按预期序列化它们:

    var REQ_PARAMS = {
      client_id: 'a81f01ef5d0036415431e8be76c8db0e',
      'duration[from]': 200000,
      'duration[to]': 205000
    };
    
$http.get('http://api.soundcloud.com/tracks.json', {params:dataToSend});

params 属性 是以 restful 方式转换查询的方式。只需转换 dataToSend 对象中的数据即可。

这是一个应该创建的URL:

https://api.soundcloud.com/tracks.json?client_id=a81f01ef5d0036415431e8be76c8db0e&duration%5Bfrom%5D=200000&duration%5Bto%5D=205000