How to prevent a can.Model with server-calculated data from getting out-of-sync

Consider a situation where a can.Model stores data which comes from a calculation on the server based on other user-entered data stored on the Model. For example, the user inputs “myval” on a can.Model, and when can.Model.save() is called, the server calculates “newval” using “myval” and returns a JSON response with {newval: calculated_value}. Can.js then stores “newval” on the model upon receiving the server response, and “newval” gets displayed to the user.

If can.Model.save() is called frequently enough with different values for “myval”, then such a situation warrants ensuring that model updates coming from the server don’t get out-of-sync with the current state of the model. One way to handle this would be to send a unique identifier for each can.Model.save() request, have the server copy the identifier into the response, and then validate on the client that a response contains the current identifier before updating the model. I looked through the Can.js code and didn’t see any built-in hook to implement something like this. I ended up monkey-patching Can.js as follows:

can.Model.prototype.original_save = can.Model.prototype.save;
can.Model.prototype.save = function(success, error) {
    if (!this.attr('request_num')) {
        this.attr('request_num', 1);
    } else {
        this.attr('request_num', this.attr('request_num') + 1);
    }
    return this.original_save(success, error);
}
can.Model.prototype.original_updated = can.Model.prototype.updated;
can.Model.prototype.updated = function(attrs) {
    if (attrs.request_num === this.attr('request_num')) {
        this.original_updated(attrs);
    }
};

While that worked, I’m wondering if there is a better way to do what I’m trying to do using Can.js that I just missed. And if not, I wonder if a hook should be added to Can.js to allow custom code to run before the server response automatically does the model update.

Don’t have time to think about your question, but did you check out the queue plugin?

I hadn’t seen the queue plugin, and yes I think that would achieve a similar result. The main difference I noticed is that the queue plugin waits for the response to be received for each AJAX request before sending the next one. And in the scenario I’m describing, that imposed delay would be unnecessary. In my scenario, it’s not important that the server receive the requests in a queued order, and it’s not important that the server reply to the requests in order. All that’s ultimately needed is that the browser ensures that the model is updated only when the response is the one for the current state of the model, as opposed to any previous state (in case the responses are received out-of-order). Nonetheless, thanks very much for pointing out the queue plugin, as that’s an incredibly useful piece of Can.js to know exists!