2

更新 我发现问题是它被阻止了。尽管数据库总是由同一个扩展创建和升级,但它并没有关闭。所以现在我正在调用“onblocked”函数。

如何“解锁”当前被阻止的数据库?将来如何防止这种情况发生?这是一个应用程序,所以没有标签正在使用它。而且由于我无法打开这些数据库甚至删除它们(这也会被阻止),我该如何关闭它们?

(对于任何想知道的人,为了从一开始就避免这个问题,您必须执行以下操作:)

mydb.onversionchange = function(event) {
    mydb.close();
};

原帖

如果我(不小心)尝试使用错误的版本打开和升级,IndexedDB 就会死掉并且无法打开。据我所知,没有办法向 indexedDB 询问最新版本的数据库。因此,如果我尝试运行以下代码两次,它会破坏数据库并且变得无法打开:

它从不抛出错误或调用 onerror。它只是静静地坐着

var db = null;

//Note, no version passed in, so the second time I do this, it seems to cause an error
var req = indexedDB.open( "test" );
req.onsuccess = function(event) { console.log( "suc: " + event.target.result.version ); db = event.target.result; };
req.onerror = function(event) { console.log( "err: " + event ); };
req.onupgradeneeded = function(event) { console.log( "upg: " + event.target.result.version ); };

//We're doing in interval since waiting for callback
var intv = setInterval(
    function()
    {
        if ( db === null ) return;

        clearInterval( intv );

        var req2 = indexedDB.open( "test", db.version + 1 );
        req2.onsuccess = function(event) { console.log( "suc: " + event.target.result.version ); };
        req2.onerror = function(event) { console.log( "err: " + event ); };
        req2.onupgradeneeded = function(event) { console.log( "upg: " + event.target.result.version ); };
    },
    50
);

所有这些代码都在我的chrome.runtime.onInstalled.addListener. 所以当我更新我的应用程序时,它会再次调用它。如果我indexedDB.open( "test" )在没有传入新版本的情况下调用,然后再次运行 setInterval 函数,它会导致一切变得不可用,并且我永远无法再次打开“测试”。如果我可以在尝试打开数据库之前查询 indexedDB 的数据库版本,这将得到解决。那存在吗?

4

2 回答 2

1

也许这有帮助?

function getVersion(callback) {
  var r = indexedDB.open('asdf');
  r.onblocked = r.onerror = console.error;
  r.onsuccess = function(event) {
    event.target.result.close();
    callback(event.target.result.version);      
  };
}

getVersion(function(version) {
  console.log('The version is: %s', version);
});

好的,根据 convo,这个小 util 函数可能会让你走上正轨:

var DATABASE_NAME_CONSTANT = 'whatever';

// Basic indexedDB connection helper
// @param callback the action to perform with the open connection
// @param version the version of the database to open or upgrade to
// @param upgradeNeeded the callback if the db should be upgraded
function connect(callback, version, upgradeNeeded) {
   var r = indexedDB.open(DATABASE_NAME_CONSTANT, version);
   if(upgradeNeeded) r.onupgradeneeded = updateNeeded;
   r.onblocked = r.onerror = console.error;
   r.onsuccess = function(event) {
     console.log('Connected to %s version %s', 
       DATABASE_NAME_CONSTANT, version);
     callback(event.target.result);
   };
}

// Now let us say you needed to connect
// and need to have the version be upgraded
// and need to send in custom upgrades based on some ajax call

function fetch() {
  var xhr = new XMLHttpRequest();
  // ... setup the request and what not
  xhr.onload = function(event) {
    // if response is 200 etc
    // store the json in some variable
    var responseJSON = ...;

    console.log('Fetched the json file successfully');
    // Let's suppose you send in version and updgradeNeeded
    // as properties of your fetched JSON object
    var targetVersion = responseJSON.idb.targetVersion;
    var upgradeNeeded = responseJSON.idb.upgradeNeeded;

    // Now connect and do whatever
    connect(function(db) {
      // Do stuff with the locally scoped db variable
      // For example, grab a prop from the fetched object
      db.objectStore('asdf').put(responseJSON.recordToInsert);

      // If you feel the need, but should not, close the db
      db.close();
      console.log('Finished doing idb stuff');
    }, targetVersion, upgradeNeeded);
  }
}
于 2013-06-11T02:48:31.917 回答
0

我认为最好始终提供版本号。如果您不这样做,您将如何管理数据库结构的升级?如果你不是一个很好的机会,你将遇到客户端上相同的数据库版本将具有其他数据库结构的情况,我认为这不是你想要的。所以我建议将版本号保存在一个变量中。

此外,在使用 indexeddb 时,您必须提供从以前版本到当前版本的升级计划。这意味着版本 4 具有一定的结构,但您必须能够从头开始获得与版本 1,2 和 3 相同的结构

于 2013-06-11T05:39:48.423 回答