Angular/Ionic 和异步 SQLite - 确保数据工厂在返回前初始化

2024-03-11

我正在使用 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 查询返回一个空结果集,承诺解析并呈现视图。


最终设法让它发挥作用。在此发布此信息以供其他遇到此问题的人使用。

数据工厂.js

  • 使用异步 SQL 调用重新设计了所有私有方法数据工厂.js回报承诺
  • 创建一个公共 initDB 方法,该方法链接对私有方法的调用(例如openDB>>dropTable_>>createTable_ETC)。还回了一个承诺(空)
  • initDB and 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

  • 使用了resolve的能力用户界面路由器
  • 我之前的尝试没有正确注入承诺
  • Added a resolve到顶级抽象状态以触发对initDB
  • 注入承诺来自initDB到子状态的resolve object
  • 将解析对象注入到控制器中

    // 应用路由(使用 ui-router) .config(函数($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();
        }
      }
    })
    

现在一切都在工作。非常感谢这篇文章澄清了我对 ui-router 的使用仅在 AngularJS 中初始化完成后才运行控制器 https://stackoverflow.com/questions/27050496/run-controllers-only-after-initialization-is-complete-in-angularjs/27050497#27050497

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Angular/Ionic 和异步 SQLite - 确保数据工厂在返回前初始化 的相关文章

  • Vue 3 Composition API 提供/注入在单文件组件中不起作用

    我正在使用 Composition API 在 VueJS 3 中创建一个库 我实现了提供 注入 如中所述docs https v3 vuejs org guide composition api provide inject html i
  • 在 Angular e2e 测试中获取浏览器路径会导致异常

    我有一个简单的 e2e 测试来验证路由重定向是否有效 跑步者 html 场景 js use strict describe e2e function beforeE
  • 使用 Angular 指令禁用文本选择

    我正在学习 JavaScript 和 AngularJS 我想使用 Angular Directive 禁用文本选择 我有该函数的 JavaScript 代码 function clearSelection if document sele
  • 如何使用有角度的材料创建卡片网格?

    我正在尝试使用 ng repeat 创建每行三张卡片的网格 我有一个普通的 javascript 对象数组附加到范围 下面的代码将为每张卡创建一个新行 div div
  • 为什么 window 与 Internet Explorer 中的 window.self 不同?

    关于我如何遇到这个问题有一个复杂的背景故事 但为什么self属性不完全等于窗口本身 在 Safari 和 Firefox 及其朋友中 结果如我所料 gt window window self true gt window window se
  • 如何使用 Playwright 使用选择器查找框架 (iframe)

    我有一个小问题 无法找到使用 Microsoft Playwright 框架的答案 根据您可以使用以下代码获取 iframe const frame page frame frame login 但是如何使用选择器来查找 iframe 并与
  • 如何在网站上使用 svg 元素制作块的屏幕截图?

    我在网站上创建了一个构造函数 其本质是将所选元素及其颜色 svg中的元素 添加到访问者选择的背景和背景颜色 png中的背景 中 然后必须单击 保存 结果 按钮并仅执行工作区的屏幕截图 我写了这个脚本 但它需要屏幕截图 但只有背景 并忽略选定
  • 本地推送通知到在应用程序内运行 JS 代码的 Win8 Live Tile

    我正在尝试将更新发送到我的应用程序的磁贴 当应用程序运行时 这可以正常工作 例如 当用户单击按钮时 我可以轻松地将磁贴更新通知发送到磁贴 我无法解决的是当应用程序无法运行时如何更新磁贴 我找到的唯一选择是使用以下命令从远程 Web 服务器拉
  • IntersectionObserver是否支持水平滚动观察?

    我制作了几个垂直滚动 IntersectionObserver 模块 但我对水平滚动感兴趣 根将是 div 观察目标将是 img 我想观察当 img 放大但 div 保持视口宽度时的变化 我什至不确定移动 Safari 是否会将缩放后的图片
  • React autoFocus 将光标设置为输入值的开头

    我有一个受控输入 最初显示一个值 我已将该输入设置为自动聚焦 但当我希望它出现在末尾时 光标出现在输入的开头 我知道这可能是因为自动对焦是在值之前添加的 但我不能 100 确定 在输入字段末尾完成光标初始化的最佳方法是什么 var Test
  • JavaScript 继承;调用和原型

    要在Javascript中实现继承 通常需要执行以下两个步骤 假设我有一个基类 Animal var Animal function name this name name 我现在想从中派生一个子类 Dog 所以我想说 var Dog fu
  • 如何通过单击链接来更改 div 的内容?

    这是我的网页的 修改后的 jsfiddle 它还有很多 而且定位是正确的 与此相反 http jsfiddle net ry0tec3p 1 http jsfiddle net ry0tec3p 1 a href class btn1 st
  • 如何使用角度材料在具有可扩展行的表格中创建嵌套垫表

    我有以下数据 id c9d5ab1a subdomain wing domain aircraft part id c9d5ab1a info mimetype application json info dependent parent
  • onclick 事件中未调用函数

    我想在每个 YouTube 链接的末尾添加一些 HTML 以在 litebox 中打开播放器 到目前为止 这是我的代码 document ready function var valid url new RegExp youtube com
  • 在 Angular 中让多个调用等待同一个 Promise

    我在一个页面上有多个使用相同服务的控制器 为了举例 我们将服务称为 USER 第一次调用 USER getUser 时 它会发出 http 请求来获取有关用户的数据 调用完成后 它将数据存储在 USER data 中 如果再次调用 USER
  • 使用 Javascript 设置 cookie [重复]

    这个问题在这里已经有答案了 我正在尝试构建我的第一个移动应用程序 它需要连接到我的 mysql 数据库并使用 json 返回数据 这很好 目前我有一个登录系统 一旦确定用户名和密码存在 它就会返回一条成功消息 对于下一步 我想在我的页面上使
  • Rails 3.1+ 的 Jasmine 与 Mocha JavaScript 测试 [已关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我对茉莉花有经验并且非常喜欢它 有谁有 Jasmine 和 Mocha 的经验 特别是 Rails 的经验吗 我想知道是否值得转用 我已经在 J
  • 主页(网格)上的缩略图现在显得模糊。如何纠正?

    我不知道这看起来是否愚蠢 但从早上开始我就无法纠正这个突然出现在我的博客网站上的错误www candidopinions in http www candidopinions in 我有一个网格视图模板 其中博客文章中的特色图像作为调整大小
  • 什么是 WKWebView 中的 WKErrorDomain 错误 4

    fatal error LPWebView encounters an error Error Domain WKErrorDomain Code 4 A JavaScript exception occurred UserInfo 0x7
  • 测量窗口偏移

    有没有一种方法可以测量 jQuery 中窗口的偏移量 以便我可以比较 固定 元素和相对定位元素的位置 我需要能够知道窗口滚动了多远 以便我可以使用该图来计算固定元素的高度 相对于视口顶部 和相对对象的高度 相对于顶部 之间的差异文件的内容

随机推荐