I am writing a PhoneGap / Cordova application with Ionic and use SQLite (with ngCordova) for permanent storage. The core of the application is a scrollable list of items that are retrieved from the SQLite database.
listController.js
.controller('ListCtrl', [ '$scope', 'dataFactory', function($scope, dataFactory) { var items = dataFactory.getAllItems().then(function(data){ $scope.allItems = data; }); } ]);
dataFactory.js
.factory('dataFactory', [function($window, $log, $q, $cordovaSQLite, dummyDataGenerator){ var db_; // ...lots of SQLite fun in here // cascading async callbacks to load the database and inject dummy data var openDB_ = function(){...}; var createTable_ = function(){...}; // etc var getAllItems = function(){ var q = $q.defer(); $cordovaSQLite.execute(db_, sqlSelectString, []).then( function(results) { $log.log("SQL SELECT successful"); var i, len, allItems = []; for(i = 0, len = results.rows.length; i < len; i++) { allItems.push(results.rows.item(i)); } q.resolve(allItems); }, function (err) { q.reject(err); } ); return q.promise; }; return { getAllItems: getAllItems }; ]}); // <-- factory
Initially, I immediately returned the factory. The controller executed getAllItems() , which was executed before the data was ready. The view was initially empty, only displaying anything upon returning to the route after the second getAllItems()
So, I tried to delay the factory return by adding the factoryReady () function and calling it only after all the internal database files were ready
var factoryReady = function(){ return { getAllItems: getAllItems }; };
And now there is an undefined error, since the whole factory is not available on the first call, and not getAllItems() , which simply returns empty-handed. I see that the SQL database is correctly written over time, but Angular throws an exception before it ends.
Now I understand that this is predictable, I read the AngularJS post : Initializing a service with asynchronous data , but I donβt quite understand how to implement a top-ranked response (by joakimbl)
What is the best way to open a service and ensure that it is not called by the controller until the internal asynchronous operation ends? Do I need to return the ENTIRE service as a promise, and not just the result from getAllItems ? I went for it, but now I'm embarrassed. Thanks.
EDIT
I also studied the use of ui-router resolve when loading the http://blog.brunoscopelliti.com/show-route-only-after-all-promises-are-resolved view, but this does not fix the internal readiness of SQL / factory data. If I return the getAllCases method, it will still be called immediately, there is nothing in the SQL database, the SQL query returns an empty result set, promises to allow and visualize the view.