Добавянето на HTTP Basic Authentication Header към Backbone.js Sync функция предотвратява актуализирането на модела при Save()

Работя върху уеб приложение, което се захранва от спокоен API, написан с рамката CherryPy на Python. Започнах да пиша потребителския интерфейс с комбинация от 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()?

Редактиране: Промених горния код, така че свойствата на модела да са достъпни чрез функцията get в success обратно извикване. Това трябва да разреши всички проблеми с паралелността с оригиналния код.

Също така добавих някои конзолни регистрационни файлове във функцията parse на модела. Колкото и да е странно, всяко от тях е undefined... Означава ли това, че Backbone.js не успява да анализира отговора ми JSON?

Редактиране 2: Преди няколко дни разбрах, че проблемът всъщност е персонализирана заглавка, която добавях към всяка заявка, за да активирам основно HTTP удостоверяване. Вижте този отговор за подробности.


person MusikPolice    schedule 07.02.2013    source източник
comment
Вашият код изглежда добре (с изключение на това, че трябва да използвате Model.urlRoot вместо Model.url, но това не е проблемът тук). По-ранните ревизии на вашия код са имали проблеми, но сте абсолютно сигурни, че точният код в текущата ви редакция все още е неуспешен?   -  person jevakallio    schedule 20.02.2013


Отговори (4)


Този код:

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

Стартира незабавно... след това няма какво да се изпълнява и започва заявката за ajax в опашка. След това отговорът идва малко по-късно и само в този момент стойностите се променят.

Изглежда също, че тези свойства не са директно върху обекта, но асинхронната обработка на записа все още се запазва, тъй като няма да получите очакваните резултати, дори ако сте коригирали този код, за да има console.log(u.get("id")) и т.н.

person Esailija    schedule 07.02.2013
comment
Вашето предложение за използване на u.get(id) вместо u.id има много смисъл, но дори и да се опитам да регистрирам тези свойства в успешно обратно извикване или в събитие за синхронизиране на модела, те остават ненастроени, така че мисля, че има още към проблема. - person MusikPolice; 20.02.2013
comment
Редактирах кода в първоначалния въпрос, за да включа вашите предложения... Все още не работи и аз съм на ръба на акъла си. - person MusikPolice; 20.02.2013
comment
@MusikPolice, ако сте дефинирали функция за анализ, тогава е ваша отговорност да върнете анализирания модел от отговора. Тази функция се използва, когато отговорът от сървъра не е директно структуриран за създаване на модел - person Esailija; 20.02.2013
comment
@MusikPolice можете да го дебъгвате във функцията за разбор така console.log( JSON.parse(JSON.stringify(response))) - person Esailija; 20.02.2013

Разбрах проблема, въпреки че все още не мога да обясня защо изобщо е проблем. Уеб приложението, което изграждам, има процес на удостоверяване, който изисква заглавка за основно удостоверяване на HTTP да бъде предадена с всички заявки.

За да направя това да работи с Backbone, отмених функцията Backbone.sync и промених ред 1398, за да добавите заглавката.

Оригинален код:

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

Променен код:

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

Функцията getAuthHash() просто връща Base64 низ, който представлява подходящата информация за удостоверяване.

По някаква причина добавянето на този хедър прави функциите за синхронизиране/запазване неуспешни. Ако го извадя, всичко работи както бихте очаквали.

Наградата все още е отворена и с радост ще я възнаградя на всеки, който може да обясни защо е така, както и да предостави решение на проблема.

Редактиране:

Изглежда, че проблемът беше начинът, по който добавях заглавката към заявката. Има хубава малка библиотека на JavaScript достъпна в Github, която решава този проблем чрез правилно добавяне на HTTP Basic Auth хедър .

person MusikPolice    schedule 21.02.2013

Тествах вашия код, той работи добре за мен.

Вижте демонстрация тук, jsfiddle.net/yxkUD/

person Array out of bound    schedule 27.02.2013
comment
Съжалявам, не добавих допълнителни подробности за проблема към въпроса. Вижте това описание за повече подробности - person MusikPolice; 27.02.2013

Опитайте се да добавите персонализиран метод beforeSend към заявката на ajax, за да добавите персонализираната заглавка.

Например: https://github.com/documentcloud/backbone/blob/master/backbone.js#L1424

person axelhzf    schedule 25.02.2013