25

有没有办法检查 IndexedDB 数据库是否已经存在?当程序试图打开一个不存在的数据库时,就会创建该数据库。我能想到的唯一方法是如下所示,我在其中测试 objectStore 是否已经存在,如果不存在,则删除数据库:

var dbexists=false;
var request = window.indexedDB.open("TestDatabase");
request.onupgradeneeded = function(e) {
    db = e.target.result;
    if (!db.objectStoreNames.contains('todo')) {
       db.close();
       indexedDB.deleteDatabase("TestDatabase");
    } else {
       dbexists=true;
    }
}
4

9 回答 9

22

在 onupgradeneeded 回调中,您可以检查版本。(e.target.result.oldversion)。如果为 0,则数据库不存在。

编辑:经过一番调查。您不能 100% 确定是否创建了新数据库。我确信的一件事是,如果 indexeddb 具有版本 1 或更高版本,您只能使用它。我相信一个数据库可以存在并且有一个版本 0(唯一的事实是你不能使用它并且将调用 onupgradeneeded 事件)。

我已经建立了自己的 indexeddbviewer。在那我打开没有版本的 indexeddb 并且如果我进入 onupgradeneeded 事件,这意味着数据库不存在。在这种情况下,我调用了中止,因此它不会升级到版本 1。这就是我检查它的方式。

var dbExists = true;
var request = window.indexeddb.open("db");
request.onupgradeneeded = function (e){
    e.target.transaction.abort();
    dbExists = false;
}

但如前所述。在这种情况下,db 可能会继续存在,但将始终调用 onupgradeneeded

于 2013-07-04T15:32:17.697 回答
9

使用 ES6,您可以使用以下代码按名称查找 IndexedDB 数据库:

const dbName = 'TestDatabase';
const isExisting = (await window.indexedDB.databases()).map(db => db.name).includes(dbName);

于 2019-12-12T16:29:13.960 回答
8

以下代码有效。我已经用 Chrome、IE 和 Opera 对其进行了测试。用本地打开的数据库和封闭的数据库和不同版本的数据库测试,所以应该是准确的。需要创建/删除数据库。但是,这将是一个原子操作,没有竞争条件的风险,因为规范承诺如果打开请求导致创建数据库,则不会并行启动打开请求。

function databaseExists(dbname, callback) {
    var req = indexedDB.open(dbname);
    var existed = true;
    req.onsuccess = function () {
        req.result.close();
        if (!existed)
            indexedDB.deleteDatabase(dbname);
        callback(existed);
    }
    req.onupgradeneeded = function () {
        existed = false;
    }
}

要使用该功能,请执行以下操作:

databaseExists(dbName, function (yesno) {
    alert (dbName + " exists? " + yesno);
});
于 2014-05-20T10:00:27.833 回答
5

我花了一个多小时玩它,基本上唯一确定和可靠的方法是使用 webkit 的webkitGetDatabaseNames.

从字面上看,有 10 种方法可以使用 onupgradeneeded 测试 DB 是否存在,但这在生产中不起作用。它要么被阻塞了几秒钟,有时完全是在删除数据库时。那些中止事务的提示是无稽之谈,因为 window.indexeddb.open("db")请求不包含事务对象......req.transaction == null

我不敢相信这是真的……

于 2014-12-05T23:21:11.410 回答
2

该函数检查数据库是否存在。使用onupgradeneeded事件,如果版本为1并且触发了该事件,则表示该数据库不存在,而是使用window.indexedDB.open(name)函数创建的,也就是说应该删除它。

当 onsuccess 事件触发,而不是 onupgradeneeded 事件(变量 dbExists 保持为真)时,表明数据库之前存在并返回真。

/**
 * Check if a database exists
 * @param {string} name Database name
 * @param {function} callback Function to return the response
 * @returns {bool} True if the database exists
 */
function databaseExists(name, callback) {
  var dbExists = true;
  var request = window.indexedDB.open(name);
  request.onupgradeneeded = function (e) {
    if (request.result.version === 1) {
      dbExists = false;
      window.indexedDB.deleteDatabase(name);
      if (callback) callback(dbExists);
    }
  };
  request.onsuccess = function (e) {
    if (dbExists) {
      if (callback) callback(dbExists);
    }
  };
}

该函数的输出是通过一个回调函数。使用形式如下:

var name = "TestDatabase";

databaseExists(name, function (exists) {
  if (exists) {
    console.debug("database " + name + " exists");
  } else {
    console.debug("database " + name + " does not exists");
  }
});

[对不起我的英语不好]

于 2014-03-23T22:51:19.757 回答
2
function databaseExists(name) {
  return new Promise(function (resolve, reject) {
    var db = indexedDB,
      req;

    try {
      // See if it exist
      req = db.webkitGetDatabaseNames();
      req.onsuccess = function (evt) {
        ~[].slice.call(evt.target.result).indexOf(name)
          ? resolve(true)
          : reject(false);
      };
    } catch (e) {
      // Try if it exist
      req = db.open(name);
      req.onsuccess = function () {
        req.result.close();
        resolve(true);
      };
      req.onupgradeneeded = function (evt) {
        evt.target.transaction.abort();
        reject(false);
      };
    }
  });
}

用法:

databaseExists("foo").then(AlreadyTaken, createDatabase)
于 2015-09-06T13:19:42.663 回答
0

如果您使用的是alasql ,则可以使用以下内容:

async existsDatabase(myDatabase) {
    return !(await alasql.promise(`
        create indexeddb database if not exists ${myDatabase};
    `));
}

如果数据库不存在,这将创建数据库,但这是迄今为止我找到的最佳解决方案。如果数据库存在,您也可以使用类似的查询删除数据库:drop indexeddb database if exists ${myDatabase};

于 2019-01-18T13:38:28.263 回答
0

另一种方法(在 Chrome 而不是 Firefox 上)是使用异步函数,如下所示:

/**
 * Checks the IndexedDB "web-server" to see if an specific database exists.
 * Must be called with await, for example, var dbFound = await doesDbExist('mySuperDB');
 * @param {string} dbName The database name to look for.
 * @returns {boolean} Whether a database name was found.
 */
async function doesDbExist(dbName) {
    var result = await indexedDB.databases();
    var dbFound = false;
    for (var i = 0; i < result.length && !dbFound; i++) {
        dbFound = result[i].name === dbName;
    }
    return dbFound;
}

然后只需按如下方式调用该函数:

var dbFound = await doesDbExist('mySuperDB');
于 2019-11-08T21:09:42.463 回答
-1

嗨,我知道这个问题已经得到回答和接受,但我认为这样做的好方法之一

var indexeddbReq = $window.indexedDB.webkitGetDatabaseNames();
                indexeddbReq.onsuccess = function(evt){
                    if(evt.target.result.contains(
                       // SUCCESS YOU FOUND THE DB
                    }
                    else{
                       // DB NOT FOUND
                    }
                }
于 2015-07-12T13:16:17.650 回答