【问题标题】:How should an app react when indexedDB is blocked当 indexedDB 被阻塞时,应用程序应该如何反应
【发布时间】:2016-10-13 22:22:31
【问题描述】:

我在另一个question 中被告知有关检测阻止和解除阻止事件“阻止的打开(或删除)未被取消,只是......被阻止。一旦解除阻止,打开(或删除)将继续进行。”

我想知道应用程序应该如何响应被阻止的事件,如果成功事件之后的路径最终仍然会发生。

如果我希望我的应用快速响应,并且遇到阻塞事件,我应该取消成功路径吗?通过路径,我指的是在成功打开数据库的情况下执行的一系列语句和函数调用和延续。

之前我假设阻塞事件阻止了成功路径的继续。我已经编写了我的应用程序,将阻塞事件视为类似于错误,这意味着操作无法继续,并且应该报告错误,然后执行其他操作或返回空闲状态。

对我来说问题是,如果成功事件最终可以继续,那么这意味着我正在分叉,并且错误路径和成功路径都会评估,并且可能会导致一些不需要的行为。

或者我最初的理解是正确的,我不需要担心取消onsuccess发生的事情,因为如果onblocked触发了那么我可以安全地推断onsuccess不会。

做下面这样的事情感觉真的很难看,但这是唯一能立即想到的避免我的问题的方法。

var r indexedDB.open(...);
var wasPreviouslyBlocked = false;
r.onsuccess = function() {
  // Cancel the success if previously blocked
  if(wasPreviouslyBlocked) {
    return;
  }
  // Proceed as normal
  doNextThing();
};
r.onblocked = function() {
  wasPreviouslyBlocked = true;
};

有没有更好的方法来应对这种情况?

【问题讨论】:

  • 我的理解是block事件不应该被接收,只要在升级事件的情况下关闭所有连接。

标签: indexeddb


【解决方案1】:

我的问题是,如果成功事件最终可以 继续,那么这意味着我正在分叉,并且错误路径和 成功路径将评估,并可能会导致一些 不受欢迎的行为。

没错。

或者我最初的理解是正确的,我不需要担心 取消 onsuccess 发生的事情,因为如果 onblocked 触发 那么我可以有把握地推断出 onsuccess 不会。

如有疑问,请实际尝试!您只需要几个选项卡和一个本地服务器。将日志记录添加到请求的blockedsuccessupgradeneeded 处理程序以及连接的versionchange 处理程序。

作为背景,想象一个标签打开数据库的 v1:

var r = indexedDB.open('db', 1);
r.onupgradeneeded = function(e) {
var db = r.result;
  // schema v1: has store s1
  db.createObjectStore('s1');
};
r.onsuccess = function(e) {
  window.db = r.result;
};

现在打开第二个选项卡并拉下想要进行升级的更新代码:

var r = indexedDB.open('db', 2);
r.onupgradeneeded = function(e) {
  // schema v1: has store s1
  // schema v2: adds store s1
  var db = r.result;
  if (e.oldVersion < 1) {
    db.createObjectStore('s1');
  }
  db.createObjectStore('s2');
};
r.onblocked = function(e) {
  console.log('uh oh...');
};

您至少可以采取三种通用方法来应对升级受阻。

  1. 让“旧”连接监视versionchange 事件并及时关闭以解除对升级的阻止。
  2. 让“新”连接监视blocked 事件并通知用户关闭其他选项卡
  3. 让“新”连接监视blocked 事件并忽略升级。

既然您对 #3 感兴趣,那么您可以这样做:

var r = indexedDB.open('db', 2);
r.onupgradeneeded = function(e) {

  // If we ever saw a blocked event, abort this upgrade.
  if (r.was_blocked) {
    r.transaction.abort();
    return;
  }

  var db = r.result;
  if (e.oldVersion < 1) {
    db.createObjectStore('s1');
  }
  db.createObjectStore('s2');
};

r.onblocked = function(e) {
  // Record that we saw a blocked event so this upgrade
  // can be ignored.
  r.was_blocked = true;
};

这与您在wasPreviouslyBlocked 尝试中的最终结果非常接近,但您的代码中有一个严重错误:您没有中止升级,只是没有实际修改架构。因此,您最终将得到一个具有模式版本 2 的数据库,但没有任何与 v2 相比的更改。如果数据库再次打开,它已经是 v2,因此升级不会触发,您将丢失您预期的架构更改。

【讨论】:

  • 一个未解决的复杂情况是,如果在第二个打开请求被阻止时发出第三个打开请求(由于第一个尚未关闭)。在这种情况下,第三个打开请求将不会运行 any 回调(甚至不会被阻塞),因此如果您需要打开请求始终快速解决或拒绝,您应该添加一个超时来执行上面的 #3如果没有回调运行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-11
  • 1970-01-01
  • 1970-01-01
  • 2022-08-12
  • 1970-01-01
  • 2013-09-17
  • 1970-01-01
相关资源
最近更新 更多