Javascript 角度/离子和异步SQLite-确保返回前数据工厂初始化

Javascript 角度/离子和异步SQLite-确保返回前数据工厂初始化,javascript,angularjs,sqlite,ionic-framework,Javascript,Angularjs,Sqlite,Ionic Framework,我正在使用Ionic编写PhoneGap/Cordova应用程序,并使用SQLite(使用ngCordova)进行持久存储。该应用程序的核心是从SQLite数据库检索的项目滚动列表 listController.js .controller('ListCtrl', [ '$scope', 'dataFactory', function($scope, dataFactory) { var items = dataFactory.getAllItems().then(func

我正在使用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;
    });

  }
]);
.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
dataFactory.js

.controller('ListCtrl', [
  '$scope',
  'dataFactory',
  function($scope, dataFactory) {

    var items = dataFactory.getAllItems().then(function(data){
      $scope.allItems = data;
    });

  }
]);
.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
现在有一个未定义的错误,因为第一次调用时整个工厂都不可用,而不是空手返回。我可以看到SQL数据库在适当的时候被正确地写入,但是Angular在这之前抛出了一个异常

我现在意识到这是可以预测的,我读过这篇文章,但不太明白如何实现排名靠前的答案(作者:joakimbl)

公开服务并确保在内部异步工作完成之前控制器不会调用服务的最佳方法是什么?我是否需要返回整个服务作为承诺,而不仅仅是
getAllItems
的结果?我试过了,但现在感到困惑。谢谢

编辑


我还研究了在加载视图时使用ui路由器的
resolve
,但这并不能修复SQL数据/工厂的内部就绪性。如果我返回
getAllCases
方法,那么它仍然会被立即调用,SQL数据库中还没有任何内容,SQL查询返回一个空结果集,promise解析并呈现视图。

最终设法让它工作。在这里发布此消息,以供其他有此问题的人使用

dataFactory.js

.controller('ListCtrl', [
  '$scope',
  'dataFactory',
  function($scope, dataFactory) {

    var items = dataFactory.getAllItems().then(function(data){
      $scope.allItems = data;
    });

  }
]);
.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
  • dataFactory.js中使用异步SQL调用重写了所有私有方法以返回承诺
  • 创建了一个公共initDB方法,该方法将调用链接到私有方法(例如,
    openDB
    >>
    dropTable
    >>
    createTable
    等)。还返回了一个承诺(空)
  • 立即从工厂返回
    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
    
现在都在工作。非常感谢这篇文章清理了我对ui路由器的使用