2
votes

I've got some strange behavior going on with a Backbone model - attributes that I set between the time that I call save() and the server responds get thrown out, replaced by the server response (which just echos the saved attributes).

Is this the way Backbone is supposed to behave? It's making my app look really insane when the server lags a bit - it overwrites my currentScreen attribute with the old one, which navigates backward a screen. Here is my code:

Interview = Backbone.Model.extend({
    urlRoot: "/interviews",
    defaults: {
        "currentScreen": 0
    }
});

and here's my Jasmine/Sinon.JS test describing what I expect (it fails with Expected 0 to equal 1.):

describe("Interview model", function() {

    beforeEach(function() {
        this.interview = new Interview;
    });

    describe("saving with a slow server response", function() {

        beforeEach(function() {
            this.server = sinon.fakeServer.create();
        });

        afterEach(function() {
            this.server.restore();
        });

        it('should not overwrite locally changed attributes on server response', function() {
            this.server.respondWith("PUT", "/interviews/1",
                       [200, { "Content-Type": "application/json" },
                        '{"id":1,"currentScreen":0}']);
            this.interview.set({id: 1, currentScreen: 0});
            this.interview.save();

            this.interview.set({currentScreen: 1}); // user navigates to next screen
            this.server.respond(); // return fake response after currentScreen changed locally
            expect(this.interview.get('currentScreen')).toEqual(1);
        });

    });
});
1

1 Answers

3
votes

Yes, this is how it's supposed to work. Your server has the canonical set of data, so it overrides the client state with whatever the true value is.

If you don't want or need the server to update the client after a save, then simply don't return any changed attributes -- just use an empty object: {}