Page 4

When AJAX Fails

Unfortunately, we’re never guaranteed that our AJAX calls will succeed. Inevitably, some of them will fail – whether purposefully or accidentally – and our UI will need to recover gracefully. So how do we go about this?

Our Controller is already listening for failing Note edits, so what’s it do when it hears one?

savingFailed : function(note){
    view.log("saving note " + note.getId() + " failed.");
    alert("failed saving note");
    note.revert();
    view.loadNote(note);
    view.setEditFormEnabled(true);
},

On line 80, we tell our Note object to rollback changes, refresh the View, and then- wait, what? Roll back changes?! That’s right, our Note object has undo history built in! How’s all that work anyways?

// manage undo history
var revert_actions = new Array();

// be able to create undo actions
function createRevertAction(func, value){
    return function(){ func(value); }
}
this.setSubject = function(subj){
    revert_actions.push(createRevertAction(function(val){ data.subject = val; }, data.subject));
    data.subject = subj;
}

Whenever we set a value on a Note, the createRevertAction() saves the previous value as well as a function that can restore that value. The closure that createRevertAction() creates is one undo step, and whenever we need to undo an object, we just need to execute that closure, which is exactly what the revert() function does.

this.revert = function(){
    while(revert_actions.length > 0){
        var action = revert_actions.pop();
        action();
    }
}

When revert() is called, it will undo each undo item in reverse order. This ensures that the most recent changes are undone first, and the most ancient changes are undone last so that the original value will be restored.

In the event of a successful AJAX call, the Controller will call clearRevertActions on the Note to reset the Undo history and cementing in the changes.

Summary

When using this undo method, you’ll need to be careful about sending multiple edits back to back and properly handling the responses. For instance, if two edits are sent back to back, and the 1st edit’s response is successful, then the call to clearRevertAction() will cement in the 2nd edit’s changes as well as the first. So if the 2nd response comes back unsuccessful, the Note won’t rollback properly since it’s undo history has already been cleared.

This problem is avoided in the demo by disabling the edit form, so it’s impossible to send multiple edits at the same time. This is typically a good solution, but if you want to allow realtime edits without disabling the form (as I’m planning with Listotron), you’ll need to expand the undo history to encompass that.

Leave a Reply

Your email address will not be published. Required fields are marked *