简体   繁体   中英

Updating Backbone model requires calling .set twice

I have a page that displays the current status of some servers. When I try to update those statuses, however, I have to first call model.save() or model.set() with a dummy value before calling model.set() with the real values, otherwise the set will fail.

Here are the relevant functions from my model: myModel.updatingFunction:

updatingFunction: function(){
    that = this;

    $.each(myServers, function(index, server){
        that.ajaxCall(server["url"]).done(function(resp, status, xhr){
            newStatus = $(resp).find("status").text();
            server["status"]=status;
            that.set("servers",[]); //view does not update if this is removed
            that.set("servers",servers);
        });
    });
},

and myModel.ajaxCall:

ajaxCall: function(url){
    return $.ajax({
        type: 'GET',
        url: url,
        dataType: 'xml'
    });
},

Based on what I have in my view, I'd expect it to update whenever the model changes.

myView.initialize:

initialize: function () {
    this.listenTo(this.model,"change", this.render);
    this.render();  
},

myView.render:

render: function() {
    this.$el.html(this.template(this.model.toJSON()));
    this.delegateEvents();
    return this;
},

But when I remove the initial .set from updatingFunction , the view fails to ever update. It isn't really hurting anything (as far as I know) by being there, so I'm ok with leaving it as is, but I'd prefer to have this working the way it should (or at least understand why I need to do this).

The servers variable is created in my fetch function, myModel.fetch:

fetch: function(){
    switch(this.get("environment")){
        case "env1":
        servers = [
        {
            "name":'env1-server1',
            "ip":'1.2.3.4',
            "heartbeat_indicator":""
        },
        {
            "name":'env2-server2',
            "ip":'1.2.3.5',
            "heartbeat_indicator":""
        }
        ];
        break;

        case "env2":
        servers = [
        {
            "name":'env2-server1',
            "ip":'2.2.3.4',
            "heartbeat_indicator":""
        },

        {
            "name":'env-server2',
            "ip":'2.2.3.5',
            "heartbeat_indicator":""
        }
        ];
        break;

        default:
        servers= [];
    }

    this.set("servers", servers);
    return servers;
},

It is not clear from your question whether or not you know for a fact that the set by itself is failing to update the model or the view.

However, I think I can venture a few guesses about what is happening.

Backbone does not update your view by default when the model changes. So, you have to trigger some means of updating the view when the model changes via a plugin or manually (using events or otherwise).

Your question implies that the second set has the desired effect on the view, leading me to believe you have implemented some means of updating the view with model changes that you haven't mentioned in your question.

So I am inferring that if you do this and get no effect:

that.set('servers', servers);

And do this and see the view update:

that.set('servers', []);
that.set('servers', servers);

...then the servers attribute was already set to the value you are setting it to.

And therefore, you are just in need of re-rendering.

It would help to see some more information about the view as well as to see where servers is coming from in the call that.set('servers', servers); .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM