Using Deferreds in jQuery 1.5
Deferreds, new in jQuery 1.5, decouple logic dependent on the outcome of a task from the task itself. They’re nothing new to the JavaScript scene; Mochikit and Dojo have implemented them for some time, but with Julian Aubourg’s AJAX rewrite landing in 1.5, deferreds in jQuery was the logical next step. With deferreds, multiple callbacks can be bound to a task’s outcome, and any of these callbacks can be bound even after the task is complete. The task in question may be asynchronous, but not necessarily.
What’s more, deferreds are now built-into $.ajax()
so you’ll get them automatically. Handlers can now be bound like this:
// $.get, an ajax request, is asynchronous by default. var req = $.get('foo.htm') .success(function( response ){ // do something with the response }) .error(function(){ // do something if the request failed }); // this might execute before the $.get() above is complete doSomethingAwesome(); // something additional to execute upon success, which might, or might not, // have fired by now. With $.ajax deferreds built-in, it doesn't matter. req.success(function( response ){ // do something more with the response // this will fire when success normally fires, or fire immediately // if prior success callbacks have already fired });
We are no longer limited to one success, error, or complete handler anymore, and instead of simple callback functions, these hooks are now self-managed first-in, first-out callback queues.
As shown in the example above, callbacks may be attached even after the AJAX request – or any observable task – has completed. For code organization this is great; the days of long unwieldy callbacks may be over. It’s almost as if $.queue()
meets pub/sub. Continue Reading »
Tags: deferreds, javascript, jQuery
Posted in jQuery | 47 Comments »
A Recursive setTimeout Pattern
Colin Snover wrote a good article about why he thinks setInterval
is considered harmful:
setInternval
ignores errors. If an error occurs in part of your code, it’ll be thrown over and over again.setInterval
does not care about network latency. When continuously polling a remote server for new data, the response could take longer than the interval amount, resulting in a bunch of queued up AJAX calls and an out-of-order DOM.
The solution is to recursively call a named function within setTimeout
, which guarantees that your logic has completed before attempting to call it again. At such, this also doesn’t guarantee that your logic will occur on a regular interval. If you want new data every 10 seconds and it takes 15 for your response to come back, you’re now behind by 5 seconds. Colin notes that you can adjust your delay if need be, but you shouldn’t really care as JavaScript timers are not accurate to begin with.
So how to do this? Consider an AJAX poller as this is a common use case:
// old and busted - don't do this setInterval(function(){ $.ajax({ url: 'foo.htm', success: function( response ){ // do something with the response } }); }, 5000); // new hotness (function loopsiloop(){ setTimeout(function(){ $.ajax({ url: 'foo.htm', success: function( response ){ // do something with the response loopsiloop(); // recurse }, error: function(){ // do some error handling. you // should probably adjust the timeout // here. loopsiloop(); // recurse, if you'd like. } }); }, 5000); })();
I’m doing three things here:
Continue Reading »
Tags: javascript, jQuery, polling
Posted in JavaScript | 8 Comments »
Using $.widget.bridge
Outside of the Widget Factory
Within jQuery UI’s widget factory exists a little method called $.widget.bridge
, which acts as a middle man between the object created with $.widget
and the jQuery API. Because bridge is a public function you do not need jQuery UI or any other part of the widget factory to use it. This is awesome and i’mma show you how.
What the widget factory calls "bridge" is an important pattern that affords us modularity and loose couping. Both Alex Sexton and Justin Meyer do an excellent job explaining it, and I highly recommend you become familiar with this design pattern if you’re not already.
$.widget.bridge
does a few things:
- Connects a regular JavaScript object to the jQuery API.
- Automatically creates instances of said object and stores it within the element(s)
$.data
cache. - Allows option changes after initialization.
- Allows calls to public methods.
- Prevents calls to private methods.
- Prevents method calls on uninitialized objects.
- Protects against multiple initializations.
jQuery UI widgets are created using $.widget("foo.bar", {});
syntax to define an object from which instances will be created. Given a DOM structure with five .foo
‘s, $('.foo').bar();
will create five instances of your "bar" object. $.widget.bridge
works inside the factory by taking your base "foo" object and giving it a public API, so that you can create instances by writing $('.foo').bar()
, and call methods by writing $('.foo').bar('baz')
. Continue Reading »
Tags: design pattern, jQuery, jquery ui
Posted in jQuery | 5 Comments »