Friday, 10 June 2016

DataSync PhoneGap/Web applications using LocalStorage

Offline / Online Data Sync

Recently I have developed a PhoneGap application in which I wanted to synchronize data with server. In this post we will see a simple method to send data from PhoneGap application / Web application using LocalStorage as a queue.
Conditions were like below:
  • Store data in queue locally in LocalStorage
  • Sync data with server if online
  • when application comes online it should start syncing the data again if any
  • upon successful sync remove from queue else try again
  • synching one item at a time
I have developed this solution using Backbone and Backbone LocalStorage plugin.

Lets start understanding the solution.

1. Backbone Model
var QueueModel = Backbone.Model.extend({
  defaults:{
    'url': null,
    'method': null //http method like GET, PUT, POST etc.
  }
});
This model is nothing but representation of ajax settings that can be found here.
2. Backbone Collection used as a Queue which is using Backbone.LocalStorage plugin. You should use singleton pattern for following backbone class.
var SyncQueue = Backbone.Collection.extend({
  
  model: QueueModel,
  
  currentModel: null, 
  
  timeOutVar: null,
  
  localStorage: new Backbone.LocalStorage(QUEUE_NAME),
  
  initialize: function() {
    setSelf(this);
  },
  
  setSyncTimer: function(milliSeconds) {
    milliSeconds = typeof milliSeconds !== 'undefined' ? milliSeconds : 5000;
    if(self.timeOutVar) { clearTimeout(self.timeOutVar); }
    setTimeout(self.startSync, milliSeconds);
  },
  
  //add model into queue 
  enqueue: function (model) {
    self.localStorage.create(model);
    self.setSyncTimer(1000);    
  },  

  //when syncing is done
  syncSuccess: function () {
    self.localStorage.destroy(self.currentModel);
    self.currentModel = null;
    self.setSyncTimer(1000);
  },
  
  //when error occurred while syncing
  syncError: function () {
    self.currentModel = null;
    setTimeout(self.startSync, 1000);
  },
  
  //sync init method
  startSync: function () {
    console.log('startSync '+ 'models length: ' + self.models.length);
    self.localStorage = new Backbone.LocalStorage(QUEUE_NAME);
    self.fetch();   
    if (self.models.length > 0 && self.currentModel === null) {
      self.currentModel = self.models[0];
      self.send();
    }
  },
  
  send: function() {   
    var ajaxJSON = self.currentModel.toJSON();
    $.ajax(ajaxJSON)
    .done(function(){
      self.syncSuccess();
    })
    .fail(function(){
      self.syncError();
    });
  }
});

Understanding above Backbone Collection

model: QueueModel = Set Backbone collection model
currentModel: null = currentModel being synced
timeOutVar: null = holds reference to timeout id
  enqueue: function (model) {
    self.localStorage.create(model);
    self.setSyncTimer(1000);    
  },  
Above function will add ajax settings model in the queue. As I said earlier this is essentially jquery ajax settings like url, method, contentType, dataType etc.
  syncSuccess: function () {
    self.localStorage.destroy(self.currentModel);
    self.currentModel = null;
    self.setSyncTimer(1000);
  },
Success callback after ajax is successful. It will remove currentModel from queue and will start synching method again.
  syncError: function () {
    self.currentModel = null;
    setTimeout(self.startSync, 1000);
  },
Error callback when ajax is unsuccessful. It will again try to sync the same model again.
  startSync: function () {
    console.log('startSync '+ 'models length: ' + self.models.length);
    self.localStorage = new Backbone.LocalStorage(QUEUE_NAME);
    self.fetch();   
    if (self.models.length > 0 && self.currentModel === null) {
      self.currentModel = self.models[0];
      self.send();
    }
  }
Above is the function which will fetch collection from localStorage and it will try to sync first model from queue.
  send: function() {   
    var ajaxJSON = self.currentModel.toJSON();
    $.ajax(ajaxJSON)
    .done(function(){
      self.syncSuccess();
    })
    .fail(function(){
      self.syncError();
    });
  }
This function will execute ajax on currentModel and will call respective callback function.
I am using above code as is in one of my application which is currently in beta mode. Improvement to above synching code can be done. If you have any suggestions please let me know.
You can find demo of above code at http://jsfiddle.net/bharatpatil/EeNH2/3/

No comments:

Post a Comment