5

我正在开发一个 Web 应用程序,该应用程序由使用 Python 的 CherryPy 框架编写的 restful API 提供支持。我开始使用 jQuery 和服务器端模板的组合来编写用户界面,但最终切换到 Backbone.js,因为 jQuery 失控了。

不幸的是,我在让我的模型与服务器同步时遇到了一些问题。这是我的代码中的一个简单示例:

$(function() {
    var User = Backbone.Model.extend({
        defaults: {
            id: null,
            username: null,
            token: null,
            token_expires: null,
            created: null
        },

        url: function() {
            return '/api/users';
        },

        parse: function(response, options) {
            console.log(response.id);
            console.log(response.username);
            console.log(response.token);
            console.log(response.created);
            return response;
        }
    });

    var u = new User();
    u.save({'username':'asdf', 'token':'asdf'}, {
        wait: true,
        success: function(model, response) {
            console.log(model.get('id'));
            console.log(model.get('username'));
            console.log(model.get('token'));
            console.log(model.get('created'));
        }
    });
});

正如您可能知道的那样,这里的想法是向该服务注册一个新用户。当我打电话时u.save();,Backbone 确实向服务器发送了一个 POST 请求。以下是相关位:

要求:

Request URL: http://localhost:8080/api/users
Request Method: POST
Request Body: {"username":"asdf","token":"asdf","id":null,"token_expires":null,"created":null}

回复:

Status Code: HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 109
Response Body: {"username": "asdf", "created": "2013-02-07T13:11:09.811507", "token": null, "id": 14, "token_expires": null}

如您所见,服务器成功处理了请求并返回了id和 的值created。但是由于某种原因,当我的代码调用时console.log(u.id);,我得到null了,当我的代码调用时console.log(u.created);,我得到了undefined.

tl;dr:为什么 Backbone.js 在调用后不持久更改我的对象save()

编辑: 我修改了上面的代码,以便在success回调中使用 get 函数访问模型属性。这应该可以解决原始代码的任何并发问题。

我还在模型的parse功能中添加了一些控制台日志记录。奇怪的是,每一个都是undefined......这是否意味着 Backbone.js 无法解析我的响应 JSON?

编辑 2: 几天前,我发现这个问题实际上是一个自定义标头,我添加到每个请求中以启用 HTTP 基本身份验证。有关详细信息,请参阅此答案

4

4 回答 4

3

这段代码:

u.save();
console.log(u.id);
console.log(u.username);
console.log(u.token);
console.log(u.created);

立即运行......之后没有任何东西可以运行,排队的 ajax 请求开始。然后响应会稍晚一些,并且只有在那个时候值才会改变。

这些属性似乎也不是直接在对象上,但是保存的异步处理仍然存在,即使您将代码更正为拥有console.log(u.get("id"))等,您也不会得到预期的结果。

于 2013-02-07T13:34:56.720 回答
3

我弄清楚了这个问题,尽管我仍然无法解释为什么这是一个问题。我正在构建的 Web 应用程序有一个身份验证过程,该过程需要一个 HTTP 基本身份验证标头与所有请求一起传递。

为了使这项工作与 Backbone 一起工作,我重写了 Backbone.sync 函数并更改了第 1398 行以添加标题。

原始代码:

var params = {type: type, dataType: 'json'};

修改代码:

var params = {
    type: type,
    dataType: 'json',
    headers: {
        'Authorization': getAuthHash()
    }
};

函数 getAuthHash() 只返回一个表示适当身份验证信息的 Base64 字符串。

出于某种原因,添加此标头会使同步/保存功能失败。如果我把它拿出来,一切都会如你所愿。

赏金仍然是开放的,我很乐意将它奖励给任何能够解释为什么会这样并提供问题解决方案的人。

编辑:

看起来问题是我将标头添加到请求的方式。Github 上有一个不错的小 JavaScript 库,它通过正确添加 HTTP Basic Auth 标头解决了这个问题。

于 2013-02-21T13:20:03.100 回答
2

我已经测试了你的代码,它对我来说很好。

在此处查看演示,jsfiddle.net/yxkUD/

于 2013-02-27T05:54:58.537 回答
1

尝试将自定义 beforeSend 方法添加到 ajax 请求以添加自定义标头。

例如: https ://github.com/documentcloud/backbone/blob/master/backbone.js#L1424

于 2013-02-25T14:45:16.113 回答