mercredi 29 avril 2015

Issue with using Resolve in combination with a SQLite Call and IonicPlatform Ready

I am trying to resolve a state:

  // Authentication & Setup
  .state('auth', {
    url: '/auth',
    templateUrl: 'templates/single-auth.html',
    controller: 'AuthCtrl',  
    resolve: {
      setupResolve: setupResolve
    }
  })

With this function setupResolve, I want to: 1. open the SQlite DB if not open already 2. get a table 'Variables' 3. If one of the values from the table passes, then resolve the state 4. otherwise: redirect to state Setup

I do this as follows in my app.js:

app.js

.run(function($ionicPlatform, $state, $rootScope) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if (window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if (window.StatusBar) {
      // org.apache.cordova.statusbar required
      StatusBar.styleDefault();
    }
  });

  //
  // state change error redirection
  $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
    //
    event.preventDefault(); // http://goo.gl/se4vxu
    switch (error) {
      case "SETUP_RESOLVE_ERROR":
        //
        $state.go('setup');
        break
      default:
        //
        $state.go('auth');
        break
    }
    console.log("$stateChangeError: error: ", error)
  });
})



.config(function($stateProvider, $urlRouterProvider) {
  //
  $urlRouterProvider.otherwise('/auth');

  //
  var authResolve = function ($q, Auth) {

    // CODE NOT RELEVANT, ONLY setupResolve
  };

  //
  var setupResolve = function(DebugConsole, $q, StorageFactory, $cordovaSplashscreen) {
    var qSetup = $q.defer();

    StorageFactory.getResolveVariable('setid').then(
      function(setId) {

        console.log("setupResolve: success", setId)
        DebugConsole.log("setupResolve: success", setId)

        //
        $cordovaSplashscreen.hide();
        qSetup.resolve(setId);

    }, function(error){

        console.log("setupResolve: error", error)
        DebugConsole.log("setupResolve: error", error)

        //
        $cordovaSplashscreen.hide();
        qSetup.reject("SETUP_RESOLVE_ERROR")

    })
    return qSetup.promise;
  };

  // Ionic uses AngularUI Router which uses the concept of states
  // Learn more here: http://ift.tt/ZzusQR
  // Set up the various states which the app can be in.
  // Each state's controller can be found in controllers.js
  $stateProvider

  // setup an abstract state for the tabs directive
  .state('tab', {
    url: "/tab",
    abstract: true,
    templateUrl: "templates/tabs.html",
    controller: "TabCtrl"
  })

  // Each tab has its own nav history stack:
  .state('tab.home', {
    url: '/home',
    views: {
      'menuContent': {
        templateUrl: 'templates/tab-home.html',
        controller: 'HomeCtrl', 
        resolve: {authResolve: authResolve}
      }
    }
  })

  // -----------------
  // Authentication & Setup
  .state('auth', {
    url: '/auth',
    templateUrl: 'templates/single-auth.html',
    controller: 'AuthCtrl',  
    resolve: {
      setupResolve: setupResolve
    }
  })

  .state('setup', {
    url: '/setup',
    templateUrl: 'templates/single-setup.html',
    controller: 'SetupCtrl'
  })

  .state('setup-accesscode', {
    url: '/setup-accesscode',
    templateUrl: 'templates/single-setup-accesscode.html',
    controller: 'SetupAccessCodeCtrl'
  })


})

SetupFactory

and then call the function getResolveVariable() in the SetupFactory, which looks as follows:

self.getResolveVariable = function(variableName, syncBoolean) {

        window.alert("getResolveVariable: start")

        var qResolve = $q.defer();

        self.getFullTable('Variables').then(function(result){

            window.alert("getResolveVariable: getFullTable: success: " + result)

            console.log("getResolveVariable", variableName, result)
            //return result0[variableName]; 

            //
            var result0 = result[0];
            qResolve.resolve(result0[variableName]) // will throw error if result = {}

        }, function(error){

            window.alert("getResolveVariable: getFullTable: error: " + error)

            console.log("getResolveVariable", error)
            //return error;

            //
            qResolve.reject(error)
        })

        return qResolve.promise;
    };


self.getFullTable = function(tableName) {

        window.alert("getFullTable: start: " + tableName)

        var queryStr = "SELECT * FROM " + tableName 
        return DBA.query(queryStr, [])
        .then(function(result) {
            return DBA.getAllObj(result, '{}'); // inside converts to object
        }, function(error){
            window.alert("getFullTable: error: " + error)
            return error;
        });
    };

query()

This function getFullTable() calls the function query() from the factory DBA and looks as follows:

self.query = function (query, parameters) {

    window.alert("query: " + query)

    window.alert("query: db = " + db)

    var qQuery = $q.defer();
    switch (db) {
      case null:
        //
        openAndProceedQuery();
        break
      default:
        //
        proceedQuery();
        break
    };

    //
    // A
    function openAndProceedQuery() {

      window.alert("query: openAndProceedQuery: start")

      self.openDb().then(function(){
        //
        // --> B
        proceedQuery();
      }, function(error){
        //
        console.log("query: openDb error" + error)
        DebugConsole.log("query: openDb error" + error)
      })
    };

    //
    // B
    function proceedQuery() {

      window.alert("query: proceedQuery: start")

      parameters = parameters || [];
      $ionicPlatform.ready(function () {
        $cordovaSQLite.execute(db, query, parameters)
          .then(function (result) {

            window.alert("query: proceedQuery: success" + result)
            qQuery.resolve(result);

          }, function (error) {
            console.log(query, parameters)
            console.warn('I found an error');
            console.warn(error);
            window.alert("query: proceedQuery: error" + error)

            qQuery.reject(error);
          });
      });
    };

    return qQuery.promise;
  };

openDb()

If the DB is not opened yet, then it calls the function openDb() in the same factory DBA, and this function looks as follows:

self.openDb = function() {

    DebugConsole.log("opening db...")
    window.alert("openDb: start")

    //
    var qOpen = $q.defer();
    $ionicPlatform.ready(function() {

      window.alert("openDb: $ionicPlatform.ready")

      // Open Db
      if(window.cordova) {
        window.alert("openDb: cordova true")
        db = $cordovaSQLite.openDB("starter.db");
      } else {
        window.alert("openDb: cordova false")
        db = window.openDatabase("starter.db", "1.0", "My app", 1024 * 1024 * 100);
      }

      // Create Tables
      self.createTables().then(function(){
        qOpen.resolve(true);
      }, function(error){
        qOpen.reject(error);
      })
    })
    return qOpen.promise;
  };

Issue

The issue is that in the last function openDb(), the ionicPlatform.ready() is not reached. It results that when opening the app, my whole screen stays white. As you can see, I put a lot of window.alerts to be able to debug it, and it all triggers the alerts as expected, with as exception the alerts within the ionicPlatform.ready() in openDb(). So it must be, that somehow the ionicPlatform.ready is the cause of the problem.

How can I bypass this? Moreover, how to properly resolve it eventually?

Note: when testing it Chrome, everything works fine! It is only when testing it on my phone that it does not work...

Aucun commentaire:

Enregistrer un commentaire