使用indexedDB时,为什么会看到“类型错误:游标未定义”?

时间:2012-09-03 03:57:09

标签: javascript html5 indexeddb

我正在尝试使用index.openCursor(此处提供keyRange.only或keyRange.bound)使用 autoIncrement:true 创建的表上的索引访问一个或多个记录。我尝试过多种变化但没有成功。有人可以使用以下代码作为模板向我展示一个工作示例:

window.indexedDB = window.indexedDB || window.webkitIndexedDB 
                || window.mozIndexedDB || window.msIndexedDB;
var ixDb; 

var ixDbIndexTest = function () {
  //Open or create the requested IndexedDB Database
  var ixDbRequest = window.indexedDB.open("testDBindexes", 2);

  ixDbRequest.onupgradeneeded = function (e) {
    ixDb = ixDbRequest.result || e.currentTarget.result;

    objectStore = 
      ixDb.createObjectStore("demoOS", 
                             { keyPath: "id", autoIncrement: true });
    objectStore.createIndex("ixdemo", "Field1",
                             { unique: false, multiEntry: false });

    //define new dummy record  
    var newRecord = {};
    newRecord.Field1 = "222";
    newRecord.Field2 = "333";
    newRecord.Field3 = "444";

    var request = objectStore.add(newRecord);

    request.onsuccess = function (e) {
      var index = objectStore.index('ixdemo');
      var range = IDBKeyRange.only("222");
      var cursorRequest = index.openCursor(range);

      cursorRequest.onsuccess = function(e) {    
        var cursor = cursorRequest.result || e.result; 
        alert(cursor.value);
        cursor.continue();
      }
    }
  };
};

window.onload = ixDbIndexTest;

更新 我修改了演示脚本,以便在仍然使用setVersion的Firefox和较旧的Chrome版本中运行。但是,您需要为Chrome添加其他版本检查逻辑,因为每次脚本运行时当前逻辑都会运行setVersion。

window.indexedDB = window.indexedDB || window.webkitIndexedDB 
                || window.mozIndexedDB || window.msIndexedDB;
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction 
                    || window.mozIDBTransaction || window.msIDBTransaction;
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || 
                     window.mozIDBKeyRange || window.msIDBKeyRange;

var ixDb;     
var ixDbIndexTest = function () {
  //Open or create the requested IndexedDB Database
  var ixDbRequest = window.indexedDB.open("testDBindexes", 1);

  ixDbRequest.onsuccess = function(e) {
    ixDb = ixDbRequest.result || e.currentTarget.result;

    if (typeof ixDb.setVersion === "function") {
      ixDbVersionRequest = ixDb.setVersion(1);

      ixDbVersionRequest.onsuccess = function (e) {
        indexTest();
      };
     }
     else {
       ixDbRequest.onupgradeneeded = function (e) {
       indexTest(); 
       };
     }
   }
 };

window.onload = ixDbIndexTest;

function indexTest() {
  var objectStore = ixDb.createObjectStore("demoOS", 
                           { keyPath: "id", autoIncrement: true });
  objectStore.createIndex("ixdemo", "Field1", 
                           { unique: false, multiEntry: false });

  //define new record with users input 
  var newRecord = {};
  newRecord.Field1 = "222";
  newRecord.Field2 = "333";
  newRecord.Field3 = "444";

  var request = objectStore.add(newRecord);

  request.onsuccess = function (e) {
    var index = objectStore.index('ixdemo');
    var range = IDBKeyRange.only("222");
    var cursorRequest = index.openCursor();

    cursorRequest.onsuccess = function(e) {    
      var cursor = cursorRequest.result || e.result; 
      if(cursor) {
        alert(JSON.stringify(cursor.value));
        cursor.continue();
      }
    }
  }
}

2 个答案:

答案 0 :(得分:4)

出现错误消息Type Error: cursor is undefined,因为您正在使用游标而不检查它是否已定义。因此,当cursor.continue()告诉IndexedDB去获取数据库中的下一个对象时,光标将耗尽实际存在的唯一对象后将被取消定义。

所以你应该做this之类的事情。在您的代码中,它看起来像:

      cursorRequest.onsuccess = function(e) {    
        var cursor = cursorRequest.result || e.result;
        if (cursor) {
          alert(cursor.value);
          cursor.continue();
        }
      }

另外,如果您知道自己只是在寻找一个对象(比如使用IDBKeyRange.only时),则可以省略cursor.continue()部分:

      cursorRequest.onsuccess = function(e) {    
        var cursor = cursorRequest.result || e.result;
        alert(cursor.value);
      }

关于你的问题对于Chrome,我无法帮助你,因为到目前为止我只专注于Firefox。我建议您尝试Chrome的最新开发版本,它实际上支持onupgradeneeded以及各种其他更新,但在我的测试中,它仍然非常错误,在Firefox中运行的代码可能会在Chrome中失败。如果这不是一个紧急的项目,那么等待一段时间让Chrome稳定下来你可能会更好。

答案 1 :(得分:0)

在onupgardeneeded事件中,您无法添加记录。

在改变之后,必须重新打开数据库以获取新的objectStore架构。所以会有两个开放

目前的Chrome是,我认为仍旧旧标准,setVersion,onupgardeneeded永远不会打电话。

newRecord必须具有keyPath'id',否则您不应在创建对象库时指定keyPath。