1

Here is some code that takes a Backbone model, saves it and then waits for the response and fires the jQuery .done() or .fail() code. This is working fine but on fail we actually want to get the returned message from the service add it to our errors object. This is all within a Backbone validate() function; after this code, we check the errors object and display the message if there is one.

It seems like if we .fail(), everything stops executing. We need to continue the validate function. I found this question/answer but it didn't seem to make a difference: Is there a way to continue after one deferred fails?

Any way to continue executing code after hitting a deferred.fail()?

addressModel.save().done(function() {
    console.log("promise done");
    model.set("...", false);
}).fail(function(response) {
    console.log("promise fail");
    if (response.responseJSON && response.responseJSON._messages) {
        _.each(response.responseJSON._messages, function(value, key) {
            errors[key] = value[0];
        });
    }
});
Community
  • 1
  • 1
Jeremy Schultz
  • 579
  • 1
  • 6
  • 26

2 Answers2

1

It's possible but tricky - at least until 3.0. The trick is:

  • Don't use .fail use .then.
  • Return a resolved deferred from the fail.

This is like signalling that we've dealt with the exception we got here:

var p = addressModel.save().then(function() {
    console.log("promise done");
    model.set("...", false);
}, function(response) {
    console.log("promise fail");
    if (response.responseJSON && response.responseJSON._messages) {
        _.each(response.responseJSON._messages, function(value, key) {
            errors[key] = value[0];
        });
    }
     return $.Deferred().resolve(); // return a resolved deferred
});

This will let you do:

p.then(function(){
  // this code runs when either failure or success happened, can also chain
});
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
0

We never could get this to work with a promise, whether it was returned by a function within Backbone's validate() or by validate() itself. But I found a solution within Backbone itself--save() will accept async: false and stall execution until a response is received, then continue from there. It probably uses a promise to do this behind the scenes.

addressModel.save(null, {
    async: false,
    success: function() {
        model.set("...", false);
    },
    error: function(model, response) {
        if (response.responseJSON && response.responseJSON._messages) {
            _.each(response.responseJSON._messages, function(value, key) {
                errors[key] = value[0];
            });
        }
    }
});
Jeremy Schultz
  • 579
  • 1
  • 6
  • 26