IndexedDB 我应该每次打开一个IDBDatabase还是只打开一个示例?

hm2xizp9  于 2022-12-09  发布在  IndexedDB
关注(0)|答案(2)|浏览(407)

我有一个SPA应用程序,它将对IndexedDB进行多次读取/写入。
打开DB是一个带有回调的异步操作:

var db; 
var request = window.indexedDB.open("MyDB", 2);

request.onupgradeneeded = function(event) { 
    // Upgrade to latest version...
}

request.onerror = function(event) { 
    // Uh oh...
}

request.onsuccess = function(event) {
    // DB open, now do something
    db = event.target.result;
};

有两种方法可以使用这个db示例:
1.在页面/SPA的生命周期内保留单个db示例?
1.当前操作完成后调用db.close(),并在下一个操作中打开一个新的db.close()
这两种模式是否都有缺陷?保持indexedDB打开是否有任何风险/问题?每个open操作是否有开销/延迟(超过可能的升级)?

ix0qys7i

ix0qys7i1#

我发现每次操作打开一个连接并不会显著降低性能。我已经运行了一年多的Chrome本地扩展,它涉及大量的indexedDB操作,并分析了数百次它的性能,但从未发现打开一个连接是一个瓶颈。瓶颈来自于没有正确使用索引或存储大的blob。
基本上,不要把你的决定建立在性能的基础上。这真的不是连接方面的问题。
这个问题实际上是代码的人体工程学,你在多大程度上与API作斗争,当你看代码时,你的代码感觉有多直观,你认为代码有多不稳定,它对新的眼睛(一个月后你自己的,或者其他人)有多欢迎。这在处理阻塞问题时是非常值得注意的,它间接地处理应用程序模态。
我个人的意见是,如果您对编写异步Javascript感到舒服,可以使用您喜欢的任何方法。如果您对异步代码感到困难,选择始终打开连接将有助于避免任何问题。我绝不建议对异步代码新手使用单个全局页面生存期变量。您也将在页面的生存期内保留该变量。另一方面,如果您发现async不重要,并且发现全局db变量更适合,那么无论如何都要使用它。
编辑-基于你的评论,我想我会分享一些我个人偏好的伪代码:

function connect(name, version) {
  return new Promise((resolve, reject) => {
    const request = indexedDB.open(name, version);
    request.onupgradeneeded = onupgradeneeded;
    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error);
    request.onblocked = () => console.warn('pending till unblocked');
  });
}

async foo(bar) {
  let conn;
  try {
    conn = await connect(DBNAME, DBVERSION);
    await storeBar(conn, bar);
  } finally {
    if(conn)
      conn.close();
  }
}

function storeBar(conn, bar) {
  return new Promise((resolve, reject) => {
    const tx = conn.transaction('store');
    const store = tx.objectStore('store');
    const request = store.put(bar);
    request.onsuccess = () => resolve(request.result);
    request.onerror = () => reject(request.error);
  });
}

使用async/await,在操作函数中使用额外的conn = await connect()行不会有太多的冲突。

cuxqih21

cuxqih212#

每次打开一个连接可能会比较慢,只是因为浏览器在做更多的工作(例如,它可能需要从磁盘读取数据)。否则,没有真实的的缺点。
由于您提到了升级,这两种模式都需要不同的方法来处理这样的场景:用户在另一个选项卡中打开您的页面,并试图打开更高版本的数据库(因为它从您的服务器下载了较新的代码)。
在每次操作一个连接的情况下,您会发现版本3上的open()失败,因为另一个选项卡可以升级到版本4。您可以注意到open失败,例如VersionError,并通知用户他们需要刷新页面。
在每页一个连接的情况下,版本3的连接将阻塞另一个标签页。v4标签页可以响应请求上的"blocked"事件,并让用户知道旧标签页应该关闭。或者v3标签页可以响应连接上的versionupgrade事件,并告诉用户它需要关闭。或者两者都有。

相关问题