Monday, October 08, 2012

Adding jQuery Deferred Support to AmplifyJS Request

A common feature request in the AmplifyJS Google Group is for the request component to support jQuery Deferreds.

For a brief overview of the request component you can check out a post I recently titled Mocking jQuery AJAX with AmplifyJS Request. In addition there are many more features listed in the official documentation.

A Little History of the Library


Before I address that request, let me go into a little history about the AmplifyJS library. When AmplifyJS was announced there was a conscious decision to not have a hard dependency on jQuery and to make it library agnostic so that you could use Dojo, MooTools, YUI, or something else. So, the publish/subscribe and store components do not use jQuery at all. The default request type shipped with AmplifyJS does utilize jQuery AJAX, but you can just as easily create a new request type that uses Dojo, MooTools, etc.

3 Ways to Provide jQuery Deferred Support


Now that we have some of the history out of the way, let's get back to the feature request. Adding a tight dependency to jQuery's Deferreds implementation isn't in the AmplifyJS roadmap since it was written to be library agnostic. You can however, write your code such that the request component plays well with jQuery Deferreds if you so choose.

1. Manually Wiring Up Deferreds


Back in October 2011 Eric Strathmeyer (@strathmeyer) answered a Google Group post regarding adding jQuery Deferreds support to amplify.requst. On of his suggestions was to manually wire up the amplify.request with jQuery Deferreds for both the success and error callbacks as shown below.


2. Using a Helper Function


If you find yourself wanting to use jQuery Deferres often with amplify.request then you can use the following helper method that both Eric and Scott González (@scott_gonzalez) have recommended.


3. Using the amplify-request-deferred Plugin


I thought some developers might want a syntax that looked more native when using jQuery Deferreds with amplify.request, so I went ahead and made the amplify-request-deferred plugin, base on the above work by Eric and Scott. To get started all you have to do is to include the plugin immediately after amplify.request.


Once you have the plugin included on your page, then you can use the plugin with syntax like the following...


Conclusion


Hopefully one of these solutions is sufficient for your needs. This is a very common request, but as I mentioned in the history section above the AmplifyJS library would rather be agnostic and not depend on any one library. I hope this is helpful to you. Thanks.

Wednesday, October 03, 2012

Mocking jQuery AJAX with AmplifyJS Request

In my opinion the most powerful part of the AmplifyJS library is the request component. The documentation is nice, but I wanted to highlight the mocking piece in particular because it is very powerful, but is easy to miss.

Being able to separate what a request looks like from the actual request itself proves to be a very effective way to develop. It protects yourself from future changes to the request/response handshake and also makes it really easy to mock responses for unit testing or for rapid prototypes.

Standard Request Define and Request Usage


The following snippet of code defines what a request should look like that communicates to twitter to get someone's recent tweets.


When you want to use the definition above you just reference the resourceId that you provided ("getTweets"), you pass any data you want to pass along, and give a callback function that will be invoked when the response comes back.


Easily Mocking the Request


If for some reason you don't have internet access, the service you are using is unstable, or you just need to unit test some code then you can mock the response by redefining the resourceId and using a function as the 2nd parameter that will be used for the mock.


Using mockJSON to Generate Randomized Data


If you are anything like me, then you are awful at making sample data. I end up with something like "Test 1", "Test 2", etc... which is laborious, looks silly, and doesn't really exercise your UI at all. If you want to semi-randomize your data for prototyping then using the mockJSON library can be helpful. The following code says to generate an array of 20 to 30 tweets that follow the format specified.

The mockJSON library, written by Menno van Slooten (@mennovanslooten), I am using has been beneficial to me when building prototypes when the backend is either unstable or not developed yet.


The following screenshot is an example of what one of the above objects looks like after using mockJSON. As you can see, the object can almost pass as a legitimate tweet (minus the actual tweet.text). mockJSON allow you to create custom keywords to extend the native ones like @MALE_FIRST_NAME, so you could conceivably make a new keyword that can make a more believable tweet.text.


If you defined the same resourceId multiple times, then the last one defined wins. So, the following output is from the mocked version using mockJSON to semi-randomize the twitter response. Note: If I wanted to switch to the real twitter, I would just need to comment out my mocked versions.



I just scratched the surface of what you can do with AmplifyJS Request. It can support caching, decoders, dataMaps, custom request types, and more. Check out the documentation for more details.

Monday, October 01, 2012

Don't Initialize All the Things in jQuery.ready()

One of the first impressions a user gets is loading your web application for the first time. Users don't have a high tolerance when it comes to page speed. They want to see something almost immediately and then be able to start interacting with your web site shortly after.

If your website utilizes JavaScript and jQuery, which many web sites do, it is very tempting to pre-initialize all of your logic (plugins, widgets, modules, event handlers, etc) in order for them to respond as fast as possible. Unfortunately, initializing ALL THE THINGS during page load works against the user's goal of loading quickly. Instead of initializing everything when the page is ready you can instead wait to initialize portions of your application until they are needed.

The following examples will show two ways of initializing a date picker. The first way will "Initialize All the Things" and the other example will use the "Just-In-Time Initialize" principle.

Example Markup


In order to convey the idea I'm trying to explain it is probably easiest to show a code sample and then talk about what is happening. We will be using the following HTML for the markup that our code examples will be using.


I am using Twitter Bootstrap to made the UI look more presentable and that is why you are seeing some extra classes attached to the above markup.

The markup shows a simple form with various input elements. In the form we will have multiple date fields that we will want to initialize using the jQuery UI datepicker widget.

Initialize All the Things


The following jQuery code looks familiar to many snippets that you'll might find across the internet, in tutorials, and possibly in your web applications.


I am using the small moment.js library to help with data manipulation. It is a handy date library that I think you'll find very compelling and rich with features.

Let's unravel what the code is doing...

  1. We wait until the document is ready before running the rest of our code.
  2. Once the DOM is ready, then select all the input elements on the page with the date class.
  3. jQuery will implicitly iterate over it's internal collection of elements and initialize each one with the datapicker jQuery UI widget.

Pros of this Technique


  • When the user interacts with any of the input.date elements they will already be setup and therefore will respond extremely quick.

Cons of this Technique


  • Your code has to wait until the DOM is ready before it can select the elements. It would be nice if you could utilize the time between when jQuery is executed and when the DOM is ready.
  • The selector doesn't have any context so it is looking throughout the whole DOM looking for input elements with the date class. This would be considered a sub-optimal selector since there is no limit to the scope or context of what is being searched.
  • The code is initializing all the elements (implicit loop) whether you need them or not. Sure, the widgets are ready when you need them, but is all that up front code necessary?
  • There is quite a bit of extra code running that isn't necessary yet before the page has even fully loaded. The affects the overall User Experience of page load, which is very key concern to users.

Just-In-Time Initialize


The following code snippet looks considerably different from the previous example, but the end result is the same and the Pros and Cons are quite different. See if you can spot out the differences.

You can view, run, and edit the above code sample from JsFiddle or you can interact with the embedded version below.



I am using the toastr library to show messages indicating when the elements were initialized. This library was created by Hans Fjällemark and John Papa.

As we did in the previous example let's outline what is happening in the code and then we will examine the Pros and Cons of this technique.

  1. We immediately set up an event handler to wait for User Input before initializing the datepicker. This allows the code to run immediately after jQuery has been executed on the page before the DOM is even ready. We don't need the DOM to be ready because we are delegating our event to the document context.
  2. We aren't initializing all the input.date element, but are only listening to the focus event. This event will propagate (a.k.a. bubble) up the DOM tree until it gets to the document at which point jQuery will determine if the item focused on matches any of the metadata it has stored. This metadata match is surprisingly fast because it is only matching this "crazy" selector against the one DOM element that was focused on and not the whole DOM tree.
  3. Our advanced selector is looking for input.date element that doesn't have the hasDatepicker class. If this is a match then that one DOM element will be initialized. After that point, if the element is focused on later the selector will no longer be a match because jQuery added the hasDatepicker class during the it's widget creation.

Pros of this Technique


  • Very fast page load speed because you are only adding an event handler to the document with some metadata that will be used later
  • There is no jQuery selection being made on DOM ready
  • There is no implicit looping going on to initialize the elements
  • Only the elements that are about to be used are initialized so there is no wasteful code being executed
  • The focused elements are only initialized once
  • This technique will also work for dynamically added date pickers added to the DOM

Cons of this Technique


  • There is some overhead of the focus event having to propagate up to the document and having jQuery check the metadata to see if there are any matching selectors for the element in question, but this is mostly a wash since it is only testing one element.

Conclusion


You want to limit initializing all the things all the time. It can be helpful if you start to think about delaying initialization until the point when you need it or possibly right before. By doing so you can utilize the time right after jQuery is executed and not wait for DOM ready then you are able to use that precious time during page load. In addition you can have a crazy weird jQuery selector that still is fast. In our last code example above had a complicated selector, but it was very fast because it is only being tested against the one element that was focused on and not the whole DOM tree.

Much of this material was gleaned from an awesome series Doug Neiner has given at the past several jQuery Conferences entitled "Contextual jQuery" (video & slides). If you haven't already seen his talks or slides I highly encourage you to go through them.