javascript - IndexedDB 作为 Angular 服务

标签 javascript html angularjs coffeescript

我正在 Angular 服务中打开一个 IndexedDB:

MyApp.factory '$database', ->
  database = null

  request = indexedDB.open 'myApp', '1'

  request.onerror = (e) ->
    console.log e

  request.onsuccess = (e) ->
    database = e.target.result

该服务还有一个方法可以返回某个集合中的所有记录:

all: (collection, resultsCallback) ->
  request = database.transaction... (omitted for brevity)

这里的问题是当我的页面加载时, Controller 将从数据库中获取所有记录。但是,可能尚未调用 IndexedDB 的成功回调,因此数据库为 null

查看 https://github.com/webcss/angular-indexedDB/blob/master/src/indexeddb.js 处的代码似乎每次查询都会再次打开数据库,并在成功回调中执行查询。

我不确定这是否完全合适。虽然这可以解决我遇到的问题,但这不会留下很多与数据库的悬空连接吗?每次需要执行查询时打开一个连接是否可以?

如果不是,Angular 中合适的解决方案是什么?

最佳答案

我在为 IndexedDB 搜索 AngularJS 包装器时遇到了您的问题。我正在查看代码,自从您几个月前查看代码以来,这些代码当然可能发生了变化。

我不相信您引用的包装器会在每次连续调用时打开和关闭数据库。您可能会注意到每个数据库访问都会调用函数 this.internalObjectStore()

internalObjectStore: function(storeName, mode) {
    var me = this;
    return dbPromise().then(function(db){
        me.transaction = db.transaction([storeName], mode || READONLY);
        me.transaction.oncomplete = module.onTransactionComplete;
        me.transaction.onabort = module.onTransactionAbort;
        me.onerror = module.onTransactionError;

        return me.transaction.objectStore(storeName);
     });
},

调用 dbPromise() 可以打开数据库,或者如果它已经打开,它只是返回打开数据库的 promise 。如果数据库已经打开,则 promise 已经解决,因此会立即调用该函数。这只是确保所有请求等到数据库最初打开的一种方法。

现在更多关于你的问题

我相信您遇到了在 AngularJS 上下文之外调用回调函数的情况。类似于 $apply() 可以将您的代码放回 Angular ,您需要一种方法来告诉 AngularJS 关于 request.onsuccess()request.onerror()。您链接到的包装器使用 $q 中的 AngularJS promise ,这会将您的代码放回到 AngularJS 上下文中。

我不擅长这种语法,所以我要恢复到标准 JavaScript。它所做的是通过数据库 promise 运行所有 API 函数。这将确保所有请求都在数据库打开后发生。同样重要的是要注意 promise 已解决的 $apply 调用。这使上下文恢复了 Angular 。

MyApp.factory('$database', function($q, $rootScope){
  var database = null,
      deferred = $q.defer(),
      dbPromise = deferred.promise,
      request = indexedDB.open('myApp', '1');

  request.onerror = function(e){
      console.log(e);
      $rootScope.$apply(function(){                  
          deferred.reject(e);
      });
  }

  request.onsuccess = function(e){
      $rootScope.$apply(function(){                  
          database = e.target.result;
          deferred.resolve();
      });
  }


  var api = {
      all: function(){ dbPromise.then(function(){...}); },
  }

  return api;

});

关于javascript - IndexedDB 作为 Angular 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22274557/

相关文章:

javascript - 促销代码链接到不同的页面

javascript - SetTimeOut 属性导致弹出阻止程序而不是新窗口

html - 在移动设备上使图像位于文本下方,而不是上方

javascript - 如何清理剩余的 watch

jquery - 打开 Accordion 组*后*如何禁用它?

javascript - 在 Backbone.js 中添加 Bing Ajax map 控件的正确位置?

javascript - 为什么我的 Android 设备无法播放通过 XHR 作为 Blob 加载的 HTML5 视频?

javascript - : Airport/Train Station departure board (html/css/jquery) 的最佳实现

javascript - AngularJS 模板重新加载并且页面消失

javascript - 删除特定参数