Tegud.NET

Blog

Tuesday, 23 August 2011

This is the first of a three part blog series where I'm going to cover a feature of jQuery: deferreds. In Part One (here) we're going to cover the very basics, what they are and a simple example. In Part Two we'll have a much more useful example, before finally we'll cover the more advanced concepts around deferreds.

What are they?

jQuery deferreds were added during the overhaul of the AJAX module. Present in many other frameworks they provide a way of managing executing code upon completion of several asynchronous operations. As suggested by their inclusion during the overhaul of AJAX in jQuery, deferreds most obvious applications relate to AJAX.  Many examples focus on how deferreds can fire callbacks when several AJAX commands return.  In this and my next blog post I’m going to try and focus on showing first how deferreds work, and then to show a real life application (which does in fact use an AJAX request, but we’ll get to that).

Deferreds are a very powerful addition to jQuery and can help you tweak the execution to improve perceieved page load time to users, manage complex asynchronous activities and much more.  Rather than dive too much into the details of the methods available with deferreds, I’m going to try and show how it works at basic level in this post, provide a more practical case study in the 2nd post and then finally move onto a more in-depth look at the methods and properties available with deferreds in jQuery (in the future I also plan to do a blog post on deferreds in other frameworks).

First, a pointless example

Not the best advert, but this simple example doesn’t have much real life application. In this example we’re going to create three deferred objects and then use setTimeout() to resolve them at different times.  When each timeout elapses one of the LI elements is turned “on”. When all three deferreds have been resolved, the final div is turned “on” and it’s text set to done.

First thing we need to do is set up the three deferred objects. This is done simply enough:

var deferredA = $.Deferred(),
    deferredB = $.Deferred(),
    deferredC = $.Deferred();

Once we have the deferred object we can then set up how resolving them is handled. First thing we do is call the when method on the jQuery object.  This returns a chainable object, but it isn’t the usual jQuery object.  Another post will cover some of the other methods available , but for now the one we really care about is .then(). Then() accepts a callback as it’s parameter, once all the arguments to when() are resolved, this callback is fired.  Basically the logic you want executed when all deferred objects are resolved goes in then().  Putting this all together our deferred setup looks like this:

 $.when(deferredA,deferredB,deferredC)
      .then(function() {
          result.addClass('On').text('Done');
      });

All three deferred are passed to the $.when() function. Our “then” callback applies the class we want and sets the text to “Done” indicating all deferreds have been resolved.

Currently because we’re generating the deferreds manually we have to resolve them manually as well.  When using the deferreds returned from jQuery’s AJAX methods, they are resolved or rejected for us. We’ll cover how to handle errors later, for now we’ll stick to the basics.  In this example we’re going to resolve the deferreds using setTimeouts of various times.

setTimeout(function() {
    deferredA.resolve();
    ul.children(':eq(0)').addClass('On'); }, 500); 
}

setTimeout(function() {
    deferredB.resolve();
    ul.children(':eq(1)').addClass('On'); }, 3000); 
}

setTimeout(function() {
    deferredC.resolve();
    ul.children(':eq(2)').addClass('On'); }, 1500);
}

As each timeout fires, it resolves it’s deferred object, as soon as all the deferreds provided to the $.when() method are resolved, it fires the callback provided to .when().

I’ve posted a working example of this to jsbin.com so feel free to see it in action/tinker.

Show me something useful already

In the next part I'm going to explore a practical use for defers, one I've used at work, and plan on introducing to my site here as well.

Friday, 22 October 2010

I'm still awaiting my copy of Javascript Patterns, hopefully it'll arrive today so I have some weekend reading.  In the meantime I thought I would post about a technique of property/method access that not everyone will know about.

Accessing a method in javascript is not a complicated operation, usually you just do <object>.<method>().  Nothing hard there.  But this can sometimes lead to somewhat more verbose code that we'd like, for example say we wanted to add or remove a class using jQuery based on a boolean value.

if(myBool)
 	myElement.addClass("Active"); 
else
 	myElement.removeClass("Active");

Sure I can store the class name in a variable and not repeat that, but it'd still leave us with a multiline statement.  Fortunately we can compress this down to a single line of code.  In javascript we can access object property and methods by using array brackets but providing a string key for the property or method name, e.g. <object>["Method"](); Its important to note the method name is in a string, if you don't provide it as a string then it will not work as expected and probably error. Programmers of C# and similar languages will be familiar with this syntax for accessing Dictionaries and similar structures.  

So how can we use this to improve the code above?  Well as we're providing the method name as a string to the "[]", we can simply control what string is placed within it. 

myElement[(myBool ? "add" : "remove") + "Class"]("Active");

Now in the above statement we use a ternary statement to decide if we prefix "Class" with add or remove.  This determines in turn which property or method you call.  Some may argue (and indeed do at my work) that this has an impact on readability, but I personally think its worth the hit in terms of concise code.  Knowing about this method of accessing properties and methods can help you write code that takes advantage of this feature, leading to much less repetition of code. 

Monday, 14 June 2010

A discussion today led to me sending out an email to all the developers at work today, which given the amount of campaigning for jQuery I've done at the company, I had hoped would'nt have been necessary.  But it was.

Basically a co-worker had asked me for some assistance with some HTML/CSS.  Unfortunately this led to me looking at his code and discovering an abundance of javascript events specified directly within the HTML.

<div id="MyElement" onclick="javascript: myFunction();">Click Me!</div>

As I mention, we've adopted jQuery quite widely throughout our products, so I pointed out that it would be much easier for everyone to follow, and easier to take advantage of jQuery's special events and event delegation functions if the events were bound in the $(document).ready() function for that page.  What's more, we know the separating style and markup is important, keeping javascript and the markup separate is also important.  By keeping them apart it makes it easier to split the javascript off into a separate file (much easier to minify AND it's cached!).

So as I say this is just a quick blog post in case anyone else is unsure about where the best place to specify javascript events are.  In my opinion, not the HTML!

Friday, 04 June 2010

As part of what I aim to be a regular series I'm covering great jQuery articles and plugins I've seen over the previous week.  I aim to post this "around" Friday every week, this week may be a little light as I've only been keeping track of articles I've seen for the last few days. 

As I say, next weeks should have a little more to it. I aim to be a lot more active on this site this year and going forwards, next stage is to implement the article system to display more in-depth articles.  In the mean time I shall endeavour to keep blogging.

Wednesday, 01 April 2009

Opps, it would appear to be 1am, and on a school night no less. I may have got slightly carried away with the JQuery RSS feed reader I'm writing for the front page. I'm taking a break from the photo gallery to work on something else. I reached the stage where I have to write the interface for loading photos into the database, which is less than fun, but needs doing. I need to work out how to import photos from a folder into the DB with minimal effort.  I am thinking of also including some kind of location based system accross the site soonish as well.

The site is now technically live, but really all that means is that it can be accessed from the web, I'll be surprised if it gets any hits currently.  I plan on going through and working out the SEO in a week or so, once I've completed the Gallery and the RSS thing. If you do stumble upon here feel free to say hi.

Wednesday, 25 March 2009

Been playing around with JQuery alot lately, really enjoying it. It takes away alot of the pain of doing things in javascript. I was talking to some guys at work today about what it can do, them being difficult were mainly pointing out you could do it all in javascript anyway, which is true, but its hardly going to do something you cant do in javascript.  But what it does do is enable you to do it much easier.  Animations for example, you could use timeouts to move things gradually, or you can use $("#someId").animate();, which is obviously way easier.  And with more people using JQuery instead of writing their own stuff, code becomes more readable and maintainable.

Alot of this website has been an experiment for me in using JQuery, so somethings could be done better, but its all part of the learning process for me.  The only real area I havent explored properly is the AJAX functions, but apart from that I've been using the other parts quite alot.  The photo gallery has some of the more advanced JQuery on the website, it handles basically all of it.  I combined that with a ASP.net image resizer and the gallery slide view was basically done. Next thing I plan on doing is the list view, which will show one gallery at a time and allow the user to scroll through it.  It will most likely also use lots of JQuery.