作者:mobiledu2502855757 | 来源:互联网 | 2023-05-27 15:57
我正在使用Ionic编写PhoneGap/Cordova应用程序,并使用SQLite(使用ngCordova)进行持久存储.应用程序的核心是从SQLite数据库中检索的项目的滚动列表.
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
最初我是马上回到工厂.控制器getAllItems()
在数据准备好之前运行了.该视图最初是空的,仅在一秒钟后返回路线时显示任何内容getAllItems()
所以我尝试通过添加一个factoryReady()函数来延迟工厂的返回,并且只有在所有内部数据库内容都准备就绪后才调用它
var factoryReady = function(){
return {
getAllItems: getAllItems
};
};
现在有一个未定义的错误,因为整个工厂在第一次调用时不可用,而不是getAllItems()
简单地空手而归.我可以看到SQL数据库在适当的时候正确写入,但Angular在完成之前会抛出异常.
我现在意识到这是可预测的,我已经阅读了AngularJS的帖子:使用异步数据初始化服务但不太了解如何实现排名靠前的答案(通过joakimbl)
在内部异步内容完成之前,暴露服务并确保控制器不会调用它的最佳方法是什么?我是否需要将ENTIRE服务作为承诺而不仅仅是结果返回getAllItems
?我有一个去,但现在我很困惑.谢谢.
编辑
resolve
在加载视图http://blog.brunoscopelliti.com/show-route-only-after-all-promises-are-resolved时,我也考虑过使用ui-router ,但这并没有解决内部的准备问题. SQL数据/工厂.如果我返回getAllCases
方法然后它仍然立即被调用,SQL数据库中没有任何内容,SQL查询返回一个空结果集,promise解析并呈现视图.
1> drjimmie1976..:
管理以使其最终运作.在这里发布这个问题给其他人.
dataFactory.js
使用dataFactory.js中的异步SQL调用重写所有私有方法以返回promise
创建了一个公共initDB方法,该方法链接了对私有方法的调用(例如openDB
>> dropTable_
>> createTable_
etc).还退了一张诺(空)
返回initDB
并getAllItems()
从工厂直接
.factory('dataFactory', [function($window, $log, $q, $cordovaSQLite, dummyDataGenerator){
var db_;
// private methods - all return promises
var openDB_ = function(dbName){
var q = $q.defer();
// ...call async SQL methods
return q.promise;
};
var createTable_ = function(){
var q = $q.defer();
// ...call async SQL methods
return q.promise;
};
// ...etc
// public methods
var 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 methods
return q.promise;
};
return {
initDB: initDB,
getAllItems: getAllItems
};
]}); // <-- factory
app.js
使用ui-router的resolve
能力
我以前的尝试没有正确地注入承诺
添加resolve
到顶级抽象状态以触发调用initDB
将承诺注入initDB
到子状态的resolve
对象中
将resolve对象注入控制器
// APP ROUTING(使用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 DB
return 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 promise
return dataFactory.getItems();
}
}
})
一切正常.非常感谢这篇文章,只有在AngularJS中完成初始化后才能清除我对ui-router 运行控制器的使用