Blog

11
February 2015

Gavin Pickin

How to Work with WebSQL and Managing Multiple Deferred and Promises

Javascript, jQuery, Techie Gotchas, WebSQL

My last post with WebSQL looked at the difference between sync and async, and how you can use Deferred and Promises. The example I showed was a simple query, so we create a deferred, run the query, when the query is completed, it resolves the deferred… and our $.when is waiting for that to complete to move on. That works great in this simple situation, what if you have to loop through 50 items, and have to update each one, and after all of them have done, you want to query the list and display those updates… how do we do that? Its easier than you think. I searched over several blogs and stack overflow questions, API docs, and got it working. I thought you would love a step by step simple example to solve this problem, so here it is.

EDIT: Ray Camden pointed out in the comments, that the Apply function is a Javascript Function, not a jQuery function - thanks for the feedback and keeping me on track.
jQuery is pretty cool, and it offers a Javascript has a function called .apply( this, array) and this is the tool we use to help use with our when. So instead of our $.when( singleDeferred) for our single deferred, we want to $.when ( all 50 of our deferred ). What I have done, is created an array of deferred, and you can call your when like this

$.when.apply( null, deferredArray ).done( function(){
     console.log( 'all inserts are done… reload the list now' );
});

 

Simple but effective… now, how do I load up the array? Let’s look at an example where we have some JSON loaded from the server and we’re inserting into our local WebSQL.

processSync: function( data ){
      var JSONData = JSON.parse( data );     
      var deferredArray = [];               
     for (var i = 0; i < JSONData.data.length; i++){
          this.syncDownTraining( JSONData.data[i], deferredArray );
     }
     
     if ( deferredArray.length > 0 ){
          $.when.apply( null, deferredArray ).done( function(){
               this.reloadList();
          });
     }
     else {
               this.reloadList();
     }
},

syncDownTraining: function( theData, deferredArray ){
      var currentDeferred = this.insertTraining( theData );
      deferredArray.push( currentDeferred );
}

 

I trimmed a little out of it, but essentially, you get some data, and parse it, and loop over it. In each loop, we pass our deferredArray in, when we call the insertData we are returned a deferred, and we add that to our deferredArray.
After we have gone through the loop, we see if the deferredArray length is greater than 0, if so, lets way for the whole array to be resolved, otherwise, lets just process and reload our list.

This is an elegant solution to an interesting problem. 
I hope this helps you, and would have helped past me, and will still help future me.

Thanks for reading.



 

by Raymond Camden
02/12/2015 03:37:46 AM

by Gavin
02/12/2015 09:20:55 AM

See, proof that just because you read it on the internet, doesn't make it right :)

Thanks Ray... I appreciate the feedback, this is part of the reason I try and share my learning experiences, because I learn too.

I'll make an edit.

Blog Search