Setting up a work queue with jQuery deferred

So I had an interesting use case and solution this past week with Backbone, collections and server synchronization. The details aside, I needed to keep the backbone collection in sync with what was stored on the server.

It seemed simple at first, just send events back to the server as they occur, right?

NO!

Everything in javascript is asynchronous. The UI is asynchronous, the network calls are asynchronous and of course user behavior is asynchronous. A user can edit a field in a row, then quickly remove that row, and you have no control over when the callback to the server completes. The user may have an edit and then delete in process, or worse, a delete then an edit of the same row if the network is busy and the UI has yet to be updated to reflect network transactions in progress. How should the server handle an edit on a deleted row?

So I needed a generic queue that can accept disparate tasks, execute them serially and watch the state of the queue. I needed to potentially not allow some actions until the queue is empty. Thankfully the folks at jQuery provide a nice set of functions to help resolve this issue.

Attached below is a sample queue. I create what will be a linked list of deferred jQuery objects. Each introduced job is followed by a “waitJob”. The queue will pause on each waitJob until it is resolved. The current wait job is stored in the “waitJob” variable, to start, this is the first deferred object.

    var queue = $.Deferred();
    var waitJob = queue;

In this function I add a callback and a wait job to the stack that will need to be resolved prior to executing the next item on the stack.

    var addJob = function(newJob) {
        queue = queue.then(newJob).then(function() { 
            waitJob = $.Deferred();
            return waitJob;
        });
    };

Now we need a method to mark the current wait job as complete. This will resolve the state of the current waitJob, and jQuery will execute the next deferred in the linked list.

    var resolvePending = function() {
        waitJob.resolve();
    };

Now we just add work:

  addJob(function() { console.log('Hello world, my work is done'); resolvePending(); }); 

Here is sample fiddle of this in action: https://jsfiddle.net/hds1ror1/2/

And there complete source: deferredTest.html

Cheers and yeah for the jQuery folks!

This entry was posted in internet, javascript, programming, tech. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s