当indexedDB被阻止时应用程序应该如何反应

时间:2016-10-13 22:22:31

标签: indexeddb

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

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

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

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

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

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

做类似下面这样的事情真的很难看,但这是我想到的唯一一个避免问题的方法。

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;
};

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

1 个答案:

答案 0 :(得分:5)

  

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

这是正确的。

  

或者我的初步理解是正确的,我不需要担心   取消成功时发生的事情,因为如果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. 让{new}连接监视blocked个事件并忽略升级。
  4. 由于你对#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,因此升级不会触发,您将错过预期的架构更改。