Let's start by looking at a typical piece of code for invoking an asynchronous operation:
This method is used to invoke a server side operation by passing a JSON data object to a controller action at the path '/members/remove'. As we see from that code, the abstractions in modern Javascript libraries such as jQuery have made really simplified doing such operations.$.post("/members/remove", data, function (result) { }
The problem I set out to solve was to provide a consistent way to handle the response which comes back from the server.
Think about it for a moment... after we invoke the above operation, typically we will need to update a piece of user interface to reflect the result. And that result may not have necessarily succeeded! Let's imagine that the member we attempt to remove is not able to be removed because of a business rule. Or if our logic fails and an exception occurs somewhere in the processing logic. Or, perhaps it did succeed after all?
In SkillsLibrary I've developed a simple little 'interface' pattern for results which get returned from asynchronous operations which looks like this:
Having a common structure for returning messages has a few benefits:{ bool Success; object Model; string Message; }
- You can create helper code to create the return messages
- You can create common client-side code for handling return messages
Focussing on the second of these benefits, think again about what can potentially happen when an async result is invoked. In the first case, let's consider that the operation fails for some reason. Your client-side code will need to know that the operation failed and be able to give the user some information about the failure. In such a case it's as simple as querying the Success property and displaying the Message to the user like so:
Whereas, if the operation succeeds, we might want to do an operation to manipulate the DOM in some way to add or remove an object from the UI. Again, this is easily achieved by using the Model property of the return message which will contain an object that represents a data item for the operation that was executed.$.post("/members/remove", data, function (result) { if( !result.Success ) { UIHelper.displayErrorElement(result.Message); } else { ... } }
You can see that, having a consistent way of returning messages from the server we are able to streamline our client-side handling code which improves maintainability by having less code that is more readable.$.post("/members/remove", data, function (result) { if( !result.Success ) { UIHelper.displayErrorElement(result.Message); } else { UIHelper.removeDOMItem($"#rootDOMElement", result.Model.Id); } }
No comments:
Post a Comment