8

我有一个基于 AngularJS 的前端,它使用 restangular 从我构建的 Django 后端获取记录。

我正在调用具有以下内容的客户列表:

var app;

app = angular.module("myApp", ["restangular"]).config(function(RestangularProvider) {
  RestangularProvider.setBaseUrl("http://172.16.91.149:8000/client/v1");
  RestangularProvider.setResponseExtractor(function(response, operation) {
    return response.objects;
  });
  return RestangularProvider.setRequestSuffix("/?callback=abc123");
});

angular.module("myApp").controller("MainCtrl", function($scope, Restangular) {
  return $scope.client = Restangular.all("client").getList();
});

Chrome 使用 HTTP 200 显示后端返回数据:

abc123({
    "meta": {
        "limit": 20,
        "next": "/client/v1/client/?callback=abc123&limit=20&offset=20",
        "offset": 0,
        "previous": null,
        "total_count": 2
    },
    "objects": [{
        "id": 1,
        "name": "Test",
        "resource_uri": "/client/v1/client/1/"
    }, {
        "id": 2,
        "name": "Test 2",
        "resource_uri": "/client/v1/client/2/"
    }]
})

但是一旦发生这种情况,我会在 Chrome 的控制台中看到以下堆栈跟踪:

TypeError: Cannot set property 'route' of undefined
    at restangularizeBase (http://172.16.91.149:9000/components/restangular/src/restangular.js:395:56)
    at restangularizeCollection (http://172.16.91.149:9000/components/restangular/src/restangular.js:499:35)
    at http://172.16.91.149:9000/components/restangular/src/restangular.js:556:44
    at wrappedCallback (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:6846:59)
    at http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:6883:26
    at Object.Scope.$eval (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:8057:28)
    at Object.Scope.$digest (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:7922:25)
    at Object.Scope.$apply (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:8143:24)
    at done (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:9170:20)
    at completeRequest (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js:9333:7) angular.js:5754

我在 restangular.js 的第 395 行做了一个断点:

L394    function restangularizeBase(parent, elem, route) {
L395        elem[config.restangularFields.route] = route;

它第一次遇到断点elem只是一个对象,route其值为client.

第二次命中断点是elem未定义route的,值为client.

任何想法为什么elem会在第二次未定义?

4

2 回答 2

19

当请求列表时,Restangular 期望来自服务器的数据是一个简单的数组。但是,如果结果数据包含结果元数据,例如分页信息,它就会分崩离析。

如果您使用的是 Django REST Framework,它将返回如下包装的结果:

{
    "count": 2,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": 1,
            "name": "Foo"
        },
        {
            "id": 2,
            "name": "Bar"
        }
    ]
}

要翻译这一点,您需要创建一个响应提取器函数。在模块配置中指定是最简单的:

angular.module('myApp', ['myApp.controllers', 'restangular']).
config(function(RestangularProvider) {
    RestangularProvider.setBaseUrl("/api");

    // This function is used to map the JSON data to something Restangular
    // expects
    RestangularProvider.setResponseExtractor(function(response, operation, what, url) {
        if (operation === "getList") {
            // Use results as the return type, and save the result metadata
            // in _resultmeta
            var newResponse = response.results;
            newResponse._resultmeta = {
                "count": response.count,
                "next": response.next,
                "previous": response.previous
            };
            return newResponse;
        }

        return response;
    });
});

这会将结果重新排列为一个简单的数组,其中包含一个包含元数据的附加属性 _resultmeta。Restangular 将对数组和对象进行处理,并且您可以在处理数组时按预期访问 _resultmeta 属性。

于 2013-06-30T01:54:28.890 回答
8

我是 Restangular 的创造者。

restangularizeBase 函数首先为您的集合调用,然后为您的每个元素调用。

从 StackTrace 来看,元素是可以的,但是一旦将集合发送到 restangularizeBase,它实际上是未定义的。请问console.log response.objects好吗?另外,请更新到最新版本。

此外,对于默认请求参数,您应该使用 defaultRequestParams 而不是 requestSuffix。requestSuffix 只能用于结尾的“/”

让我知道我是否可以为您提供更多帮助!

于 2013-06-26T00:30:33.207 回答