【问题标题】:Why is `onversionchange` never called in Chrome 27?为什么在 Chrome 27 中从未调用过“onversionchange”?
【发布时间】:2013-06-14 01:57:25
【问题描述】:

当我尝试升级数据库时,尽管抛出了IDBVersionChangeEvent 事件(它被发送到我的onupgrade 回调),但永远不会调用onversionchange!这导致我有一个blocked 事件。我不知道如何让它调用正确的处理程序。

使用 Chrome 27

//Account for different names of indexedDB
window.indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;

//Account for different names of transaction and key range
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;

var req = indexedDB.open( "test6", 2 );
req.onupgradeneeded = function(event)
{
    console.log( "This upgrade gets called" ); 

    //These do nothing
    event.target.onversionchange = function(event) { console.log( "request version change" ); };
    event.target.result.onversionchange = function(event) { console.log( "database version change" ); };
};

req.onsuccess = function(event)
{
    console.log( "This Success is called" ); 

    //These do nothing
    event.target.onversionchange = function(event) { console.log( "request version change" ); };
    event.target.result.onversionchange = function(event) { console.log( "database version change" ); };
};

req.onerror = function(event)
{
    console.log( "This error is not called" ); 
};

req.onblocked = function(event)
{
    console.log( "This blocked is sometimes called" ); 
};

//This also does nothing
req.onversionchange = function(event) { console.log( "request version change" ); };

我已经尝试在任何地方添加它,但它永远不会被调用!

编辑(未解决) 看来indexedDB.deleteDatabase() 调用了onversionchange 处理程序!不知道为什么会这样,但升级不会。

【问题讨论】:

    标签: html google-chrome google-chrome-extension indexeddb google-chrome-app


    【解决方案1】:

    onversionchange 事件是dispatched by database 实例。所以你应该这样听

    req.onsuccess = function(e) {
      db = e.target.result;
      db.onversionchange = function(e) {
         db.close();
      }
    }
    

    【讨论】:

    • 不起作用。它仍然永远不会触发。如果您查看我的代码,您会发现我已经在这样做了。
    • 有你的电话db.close() 吗?在测试之前,关闭所有浏览器实例并确保没有软件更新挂起。
    • 你能测试一下上面的代码吗? onversionchange 会为你打电话吗?
    • 唐,它不会被调用。你听错了对象。正如我所说,你听不见数据库对象。
    • 请再看一遍我的代码。你看到我有event.target.result.onversionchange = function(event) { console.log( "database version change" ); }; 吗?那就是监听数据库。仍然没有被调用。
    【解决方案2】:

    当不同的请求尝试增加版本时,会在数据库中触发 versionchange 事件。所以,如果你添加到上面代码的底部

    var req2 = indexedDB.open( "test6", 3 ); // <- note: "3"
    req2.onblocked = function(e) { console.log("this will be called"); };
    req2.onupgradeneeded = function(e) {
        console.log("this will be called once the first connection is closed");
    };
    

    应该调用你原来的 versionchange 事件处理程序,虽然我自己没有测试它。

    编辑:它适用于我的 chrome 28.0.1500.45 beta:

    <script>
    
    var req = indexedDB.open( "test6", 2 );
    
    req.onsuccess = function(event)
    {
        console.log( "This Success is called" ); 
    
        //These do nothing
        event.target.onversionchange = function(event) { console.log( "request version change 2" ); };
        event.target.result.onversionchange = function(event) { console.log( "database version change 2" ); };
    };
    
    req.onerror = function(event)
    {
        console.log( "This error is not called" ); 
    };
    
    req.onblocked = function(event)
    {
        console.log( "This blocked is sometimes called" ); 
    };
    
    var req2 = indexedDB.open( "test6", 3 ); // <- note: "3"
    req2.onblocked = function(e) { console.log("this blocked will be called"); };
    req2.onupgradeneeded = function(e) {
        console.log("this will be called once the first connection is closed");
    };
    
    </script>
    

    给予

    This Success is called dogs.html:7
    database version change 2 dogs.html:11
    this blocked will be called dogs.html:25
    

    【讨论】:

    • 你能在 chrome 中试试这个吗?它仍然永远不会触发db.onversionchange。它确实调用了db.onupgradeneeded,但不是onversionchange
    【解决方案3】:

    onblocked 触发的事实很可能意味着您在其他地方打开了一个数据库连接,可能在另一个选项卡中。

    onversionchange 事件在该其他选项卡(或可能许多选项卡)中触发。

    您需要在那里侦听数据库连接对象上的onversionchange 事件,并在那里处理它。例如,您可以关闭那里的数据库连接,并显示一个对话框,指示用户他们应该重新加载页面以获取新的数据库版本。

    做这样的事情:

      req.onsuccess = function(event)
      {
          var db = event.target.result
          db.onversionchange = function(event) { 
            document.body.innerHTML = "" // or a more subtle way to disable the page
            db.close()
            window.alert("please reload the page for the latest version")
          }
      };
    

    我最近没有与 IndexedDB 密切合作,但我想我记得onblocked 会触发,无论其他活动的数据库连接是否有一个关闭数据库的 onversionchange 侦听器。我认为您将始终首先获得onblocked,如果/当所有连接都已关闭时,您将获得onsuccess 事件,允许您使用新数据库。

    您在执行indexedDB.deleteDatabase() 时看到onversionchange 事件触发的原因是您在该选项卡中打开连接时尝试删除数据库。

    【讨论】:

    • 我没有其他标签。这是一个托管/打包的应用程序。它只有一个实例。我同意数据库在某个地方打开而不是关闭,但我从哪里得到该通知。我打开的唯一地方是该托管应用程序的唯一实例。这就是我难过的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-13
    • 1970-01-01
    相关资源
    最近更新 更多