Skip to content Skip to sidebar Skip to footer

Angular/ionic And Async Sqlite - Ensuring Data Factory Initialised Before Return

I'm writing a PhoneGap/Cordova app with Ionic, and using SQLite (with ngCordova) for persistent storage. The core of the app is a scrolling list of items which are retrieved from t

Solution 1:

Managed to get it working in the end. Posting this here for anyone else having the issue.

dataFactory.js

  • Reworked all private methods using async SQL calls in dataFactory.js to return promises
  • Created a public initDB method which chained calls to the private methods (e.g. openDB >> dropTable_ >> createTable_ etc). Also returned a promise (empty)
  • Returned initDB and getAllItems() from the factory immediately

    .factory('dataFactory', [function($window, $log, $q, $cordovaSQLite, dummyDataGenerator){    
    
      var db_;
    
      // private methods - all return promisesvar openDB_ = function(dbName){
    
        var q = $q.defer();
        // ...call async SQL methodsreturn q.promise;
      };
    
      var createTable_ = function(){
        var q = $q.defer();
        // ...call async SQL methodsreturn q.promise;               
      };
    
      // ...etc// public methodsvar initDB = function(){
    
        var q = $q.defer();
        // successively call private methods, chaining to next with .then()
        openDB_("myDB").then(function(db){
          var schema = "...SQL schema here..."
          dropTable_(db, "FirstTable", schema).then(function(tableName){
            // ...etc// when all done, resolve the promise
            q.resolve();
          })
        })
        return q.promise;
      }
    
      var getAllItems = function(){
    
        var q = $q.defer();
        // ...call async SQL methodsreturn q.promise;
      };
    
      return {
        initDB: initDB,
        getAllItems: getAllItems 
      };
    
    ]}); // <-- factory

app.js

  • Used the resolve ability of ui-router
  • My previous attempts had not correctly injected promises
  • Added a resolve to the top-level abstract state to fire off the call to initDB
  • Injected the promise from initDB to the child state's resolve object
  • Inject the resolve object into the controller

    // APP ROUTING (using ui-router) .config(function($stateProvider, $urlRouterProvider){

    $stateProvider// top-level abstract state that houses Ionic side menu & nav
      .state('app', {
        url: '/app',
        abstract: true,
        templateUrl: "templates/sideMenu.html",
        resolve: {
          dbReady: function($log, dataFactory){
            // (1) init the DBreturn dataFactory.initDB().then(function(){
              $log.log("initDB promise resolved");
          });
        }
      }
    })
    
    // the following states are all child states of app
    
    .state('app.items', {
      url: "/items",
      views: {
        menuContent: {
          templateUrl: "templates/gbCaseList.html",
          // (3) now we can inject the items promise into our controller
          controller: function($scope, $log, items){
            // (4) uses resolved items variable injected by ui-router$scope.allItems = items;
          }
        }
      },
      resolve: {
        // (2) note that we MUST inject the dbReady promise, if we don't this will instantiate immediately
        items: function(dbReady, $log, dataFactory){
          // the following call returns a promisereturn dataFactory.getItems();
        }
      }
    })
    

All working now. Massive thanks to this post for clearing up my use of ui-router Run controllers only after initialization is complete in AngularJS

Post a Comment for "Angular/ionic And Async Sqlite - Ensuring Data Factory Initialised Before Return"