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
andgetAllItems()
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 toinitDB
- Injected the promise from
initDB
to the child state'sresolve
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"