我正在使用 Ionic 编写 PhoneGap/Cordova 应用程序,并使用 SQLite(与 ngCordova)进行持久存储。该应用程序的核心是从 SQLite 数据库检索的项目的滚动列表。
列表控制器.js
.controller('ListCtrl', [
'$scope',
'dataFactory',
function($scope, dataFactory) {
var items = dataFactory.getAllItems().then(function(data){
$scope.allItems = data;
});
}
]);
数据工厂.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
最初我是立即返回工厂。控制器做了getAllItems()
它在数据准备好之前运行。视图最初是空的,仅显示一秒钟后返回路线时的任何内容getAllItems()
因此,我尝试通过添加factoryReady()函数来延迟工厂的返回,并且仅在所有内部数据库内容准备就绪后才调用它
var factoryReady = function(){
return {
getAllItems: getAllItems
};
};
现在有一个未定义的错误entire第一次调用时工厂不可用,而不是getAllItems()
只是空手而归。我可以看到 SQL 数据库正在正确写入,但 Angular 在完成之前抛出了异常。
我现在意识到这是可以预见的,我读过这篇文章AngularJS:使用异步数据初始化服务 https://stackoverflow.com/questions/16286605/initialize-angularjs-service-with-asynchronous-data但不太明白如何实现排名最高的答案(作者:joakimbl)
公开服务并确保在内部异步内容完成之前控制器不会调用它的最佳方法是什么?我是否需要将整个服务作为承诺返回,而不仅仅是结果getAllItems
?我尝试过这个,但现在很困惑。谢谢。
EDIT
我还研究过使用 ui-routerresolve
加载视图时http://blog.brunscopelliti.com/show-route-only-after-all-promises-are-resolved http://blog.brunoscopelliti.com/show-route-only-after-all-promises-are-resolved但这并不能解决 SQL 数据/工厂的内部准备情况。如果我返回getAllCases
方法,那么它仍然会立即被调用,SQL 数据库中还没有任何内容,SQL 查询返回一个空结果集,承诺解析并呈现视图。