【问题标题】:"Cannot call method 'transaction' of undefined" error in indexedDBindexedDB 中的“无法调用未定义的方法‘事务’”错误
【发布时间】:2014-03-26 17:54:48
【问题描述】:

下面是我的代码。它第一次运行良好,但是一旦我刷新页面,它就会生成一个未捕获的 TypeError:无法调用未定义的方法“事务”。

基本上,我从数据库中检索数据并将其编码为可用的 JSON 数据类型,以避免在我的表中插入问题。

$(document).ready( function() {

//prefixes of implementation that we want to test
window.indexedDB = window.indexedDB ||
                   window.mozIndexedDB ||
                   window.webkitIndexedDB ||
                   window.msIndexedDB;

//prefixes of window.IDB objects
window.IDBTransaction = window.IDBTransaction ||
                        window.webkitIDBTransaction ||
                        window.msIDBTransaction;

window.IDBKeyRange = window.IDBKeyRange ||
                     window.webkitIDBKeyRange ||
                     window.msIDBKeyRange

if(!window.indexedDB){ //alert user if browser does not support
    window.alert("Your browser doesn't support a stable version of IndexedDB.")
}

var request = window.indexedDB.open("runningClub", 1); //create a runningClub database

var browserDB;

request.onsuccess = function(event){
    browserDB = request.result;
};

var raceIDs = [];

$(".raceID").each( function () {
    raceIDs.push(" raceID = " + $(this).val());
});

$.ajax({
    url: 'controller/AJAX/userAction.php',
    type: 'post',
    dataType: 'json',
    data: { statement : "getRaceResult", raceIDs : raceIDs },
    success: function(data) {

        const results = data;

        request.onupgradeneeded = function(event){
            var browserDB = event.target.result;
            var objectStore = browserDB.createObjectStore("raceResult", {keyPath: "resultID"});
            for(var i in results){
                objectStore.add(results[i]);       
            }
        }

        var objectStore = browserDB.transaction("raceResult").objectStore("raceResult");

        objectStore.openCursor().onsuccess = function(event){
            var cursor = event.target.result;
            if (cursor){
                $("#memberName").append("<option>" + cursor.value.memberName + "</option>");
                cursor.continue();
            }
        };
    }
});
});

【问题讨论】:

    标签: javascript indexeddb


    【解决方案1】:

    感谢您发布(几乎)全部代码。不幸的是,如果不知道来自后端的数据对象的结构,我无法完全复制您的问题。介意发布吗?

    也就是说,我很确定您的问题是使用 const。

    const results = data;
    

    我不相信这种类型的数据是“structured clone”-able。鉴于 JSON 是完全可克隆的,这就是我想象的从您的 API 返回的内容(与例如可以评估以产生 function 的 JavaScript 相比),此关键字的使用似乎可能是您问题的罪魁祸首。

    更新 1 解决这个问题,您的异步编程存在不少问题。

    • 数据库在ajax请求之前打开,而不是在成功回调之后。将其移至回调中似乎是谨慎的做法。
    • browserDB 在 success 回调中定义,不能保证在异步操作完成之前运行(因此 browserDB 变为未定义)
    • request.onsuccess 被调用了两次(您可能没有意识到这一点,因为这是一种奇怪的行为):无论是在没有触发 upgradeneeded 事件时还是在触发 upgradeneeded 事件时,所以您重新定义 browserDB 可能是在 DB 时意外还不存在

    更新 2 这是一个大部分工作,simplified Fiddle。我为我花费了多少时间让您的代码正常工作而感到难过。

    更多问题(除了const):

    • 硬编码数据库版本
    • 重复使用versionchange 事件来添加/获取数据是个坏主意
    • 需要使用readwrite事务添加数据
    • openCursor - 但不为 resultID keypath 提供参数
    • 在获取数据之前你没有监听成功的添加
    • 在获取数据之前,您没有链接成功事件以进行添加

    当前的循环方法是站不住脚的。但是我使用单个添加和游标获取它。您可以重构回多重添加方法,但您需要注意异步(根据我所看到的,我建议您坚持使用简单)。

    $.ajax({
      url: '/echo/json/',
      type: 'post',
      dataType: 'json',
      data: {
        json: JSON.stringify({
          resultID: new Date().getTime(),
          raceID: "1",
          memberID: "824",
          runtime: "00:31:26",
          memberName‌: "Mark Hudspith"
        })
      },
      success: function (data) {
        var request,
          upgrade = false,
          doTx = function (db, entry) {
            addData(db, entry, function () {
              getData(db);
            });
          },
          getData = function (db) {
            db.transaction(["raceResult"], "readonly").objectStore("raceResult").openCursor(IDBKeyRange.lowerBound("0")).onsuccess = function (event) {
              var cursor = event.target.result;
              if (null !== cursor) {
                console.log("YOUR DATA IS HERE", cursor.value.memberName‌);
                cursor.continue();
              }
            };
          },
          addData = function (db, entry, finished) {
            var tx = db.transaction(["raceResult"], "readwrite");
            tx.addEventListener('complete', function (e) {
              finished();
            });
            tx.objectStore("raceResult").add(entry);
          };
        request = window.indexedDB.open("runningClub");
        request.onsuccess = function (event) {
          if (!upgrade) {
            doTx(request.result, data);
          }
        };
        request.onupgradeneeded = function (event) {
          var db = event.target.result;
          db.createObjectStore("raceResult", {
            keyPath: "resultID"
          });
          setTimeout(function () {
            doTx(db, data);
          }, 5000);
        }
      }
    });
    

    【讨论】:

    • 后端是这样的: case 'getRaceResult': $raceResults = $user->getAllRaceResult($raceIDs);回声 json_encode($raceResults);休息;
    • 粘贴失败,但删除“const”关键字,替换为var,给我试一下。
    • PHP,很酷,我完全关注 - 但我需要 $raceResults 的值。我要做的是确认您的数据是可存储的。 IDB 无法存储所有类型的 JavaScript 数据。
    • 返回数据之一是:[{"resultID":"1","raceID":"1","memberID":"824","runtime":"00:31: 26","memberName":"Mark Hudspith"}]
    • 感谢您的努力
    猜你喜欢
    • 2013-10-23
    • 2019-05-23
    • 1970-01-01
    • 2014-09-18
    • 2011-09-30
    • 1970-01-01
    • 1970-01-01
    • 2012-10-29
    相关资源
    最近更新 更多