Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knockout js best practices ajax error handling

What best practices for Knockout js have you used when ajax json responses come back bad.

How do you create your mappings to display an error has occured to the user? How do you change the binding of a form in Knockout js to accommodate errors?

I send back a response object of {response:"success",data:{}}, which kind of means that there are 3 levels of error:

  1. The Model error (json object response of "failure", with model data of what fields were wrong)
  2. The Server error (no response from server)
  3. Server responds with error code

Have not figured out a clean viewmodel way of displaying an error message which Is why I'm asking.

like image 602
maxfridbe Avatar asked Feb 14 '12 23:02

maxfridbe


2 Answers

The way I've come up with error handling in KO has been to create a base class:

errorHandlingViewModel = function () {
    var self = this;
    self.ErrorText = ko.observable();
    self.errorHandler = function (jqXHR, textStatus, errorThrown) {
        self.ErrorText('An error has occured, please refresh the page and try again in a little while. (' + textStatus + ':' + errorThrown + ')');
    };
    self.validationErrorHandler = function (err) {
        //todo
        alert('validation error ' + err);
    }
    self.successHandler = function (data, onSuccess) {
        if (data.result == "success") {
            if (onSuccess) {
                onSuccess(data.data);
            }
        }
        else {
            if (data.data && data.data.Tag) {
                if (data.data.Tag == "ValidationError") {
                    validationErrorHandler(data.data.Tag);
                }
            }
            errorHandler(null, data.result, data.data);
        }
    };
};

This has an observable ErrorText field.

All my ViewModels that need this error handling can use prototypal inheritance:

viewModel.prototype = new errorHandlingViewModel();
var mainViewModel = new viewModel();
ko.applyBindings(mainViewModel, $("#locationTOApplyBindingTo")[0]);

In this view models ajax calls look like:

$.ajax({
    type: 'POST',
    url: myURL,
    data: myData,
    success: function (data) {self.successHandler(data,success);},
    error: self.errorHandler
}); //end ajax

The UI is a simple data-bind:

<div class="error" data-bind="visible:ErrorText">
    <div class="innerMSGContainer">
        <div class="innerMSG" data-bind="text:ErrorText"></div>
    </div>
</div>

Javascript Try-Catch is still missing from this model as I am unsure to the placement

like image 132
maxfridbe Avatar answered Oct 02 '22 06:10

maxfridbe


Personally I would only update the knockout models upon success. This then leaves the models in the same state as prior to the error.

In the case of an error, you could do anything you want to tell the user there has been an error. I would use humane.js to show a message to the user that the update or creation has failed for some reason. In your three cases for model error, no response or server error, you could check the state of the post in the error function and choose a different message to display to the user

They then have the freedom to do the same thing again, or correct their mistake and try again.

$.post("somewhere")
.success(function() {
    // update knockout models here
})
.error(function() {
    // show error message to user
})
.complete(function() {
    // reset any temporary variables
});
like image 32
soniiic Avatar answered Oct 02 '22 06:10

soniiic