Tuesday, October 30, 2012

Amplify.js


Request Component

The amplify.request component sets out to make data retrieval more maintainable. It does this by separating the definition of a request from the actual implementation of requesting the data. The definition of the request is only responsible for deciding the caching strategy, server location, data type, decoders, headers, etc. While the actual requestor code only needs to know a request ID. This allows for a data layer which can make your application much easier to test and more agile to change.

Request Define API

The role of amplify.request.define is to allow you to focus on only defining the implementation of retrieving data. The API for amplify.request.define can be very simple, but also has numerous optional parameters that you can leverage, including some that you can provide custom implementations of your own.

Define a Request

  1. amplify.request.define( string resourceId, string requestType [, hash settings ] )
  • resourceId: Identifier string for the resource
  • requestType: The type of data retrieval method from the server. There is currently one built in requestType (ajax), but you can also define your own.
  • settings (optional): A set of key/value pairs that relate to the server communication technology.
    • Any settings found in jQuery.ajax()
    • cache: Providing different caching algorithms for the request and response
      • boolean: Cache the data in-memory for the remainder of the page load
      • number: Cache the data in-memory for the specified number of milliseconds
      • string: Persistent client-side cache using amplify.store
        • "persist": Will use the first available storage type as default
        • "localStorage", "sessionStorage", etc. ... 
    • decoder: A way to parse an ajax response before calling the success or error callback. There is currently one built in decoder (jSend), but you can also define your own. By default no decoder is used unless you set it.
      • "jsend": A specification on how JSON responses should be formatted
Example Usage
  1. amplify.request.define( "getContactDetails""ajax"{
  2.   //Amplify will replace {id} with data passed to it
  3.   url: "/Contact/Details/{id}"
  4.   dataType: "json",
  5.   type: "GET"
  6.   //Response will be cached for 15 seconds
  7.   cache: 15000     
  8. });

Request API

Once you've defined your request, then the next step would be to go ahead and call the amplify.request method. Thankfully, most of the hard part was defining the definition of the request, so calling amplify.request is fairly straightforward.

Simplified Request

  1. amplify.request( string resourceId 
  2.   [, hash data [, function callback ]] )
  • resourceId: Identifier string for the resource
  • data (optional): an object literal of data to be sent to the resource
  • callback (optional): a function to call once the resource has been retrieved
Example Usage
  1. amplify.request( "getContactDetails"
  2.   //Amplify will resolve url to "/Contact/Details/4"
  3.   { id: 4 }
  4.   function( data ) {
  5.     console.log( data );
  6.   });

Request with Hash Settings

  1. amplify.request( hash settings )
  • settings
    • resourceId: Identifier string for the resource
    • data (optional): Data associated with the request
    • success (optional): Function to invoke on success
    • error (optional): Function to invoke on error
Example Usage
  1. amplify.request({ 
  2.   resourceId: "getContactDetails",
  3.   //Amplify will resolve url to "/Contact/Details/4"
  4.   data: { id: 4 }
  5.   success: function( data ) {
  6.     console.log( data );
  7.   },
  8.   error: function( message, level ) {
  9.     console.log( level + ": " + message );
  10.   }
  11. });

Sample Application

Now we will update the sample application from above and swap out the call to $.ajax() to use amplify.request instead.
  1. var hackerNews = (function( $, undefined ) {
  2.   var pub = {};
  3.  
  4.   pub.init = function() {
  5.     //...
  6.  
  7.     //Define getNews AJAX JSONP request in Amplify
  8.     amplify.request.define( "getNews""ajax"{
  9.       url: "http://api.ihackernews.com/page" + 
  10.         "?format=jsonp"
  11.       dataType: "jsonp",
  12.       cache: 30000
  13.     });                
  14.   };
  15.      
  16.   //...
  17.      
  18.   function getNews( callback ) { 
  19.     //Request for news from Amplify        
  20.     amplify.request({
  21.       resourceId: "getNews",
  22.       success: function( data ) {
  23.         if ( callback ) callback ( data );
  24.       },
  25.       error: function( message, level ) {
  26.         console.log( level + ": " + message );
  27.       }
  28.     });        
  29.   }
  30.      
  31.   //...
  32.      
  33.   return pub;
  34. }( jQuery ));
  35.  
  36. hackerNews.init();
  37. hackerNews.getAndDisplayNews();
You can view, run, and edit the above source code from jsFiddle.
We first defined what the request will look like and placed that in our init method. We define the request as getNews, use the built in ajax type, and then pass some options which include common $.ajax() settings such as url and dataType, but also includes a amplify.request specificcache setting where we will cache the response of the request for 30000 milliseconds (30 seconds).
After defining our request with amplify.request.define, we then swapped out the $.ajax() code that was in the getNews method and replaced it with amplify.request referencing the resourceIdwe previously defined, a success callback, and an error callback method.
With caching now on when the user clicks on the Refresh button there will be a 30 second period where no actual ajax request is being made to the server. You can verify this using your web developer tools in your browser. Once the cache has been cleared after 30 seconds, then the real request will proceed to the server and return fresh results that will be in-turn cached for another 30 seconds.
By making these two small changes the application still works as it did before and we didn't have to change any other code. The power of Amplify is in having the definition adapt with changes while leaving the request functionality untouched. Just think what might happen if the backend switched to web sockets instead or instead of JSON being returned it was XML. Towards the end of this article we will take another look at the power of making this abstraction.

Benefits

  • Separate out the definition from a request from the actual request for data from the server
  • Ability to provide alternative caching and decoding implementations

http://msdn.microsoft.com/en-us/magazine/hh147623.aspx
http://amplifyjs.com/

No comments:

Post a Comment