【问题标题】:Cannot read property 'result' of undefined IndexedDB无法读取未定义 IndexedDB 的属性“结果”
【发布时间】:2019-05-27 03:04:50
【问题描述】:

我正在尝试从 IndexedDB 数据库中获取点赞数。但是,我收到此错误

未捕获的类型错误:无法读取 IDBRequest.request.onsuccess 处未定义的属性“结果”

它正在抛出错误

console.log(request.result)

parent.addEventListener('click', event => 
{
    //Get number of likes
    var transaction = db.transaction(['posts']);
    var objectStore = transaction.objectStore('posts');
    var request = objectStore.get(parseInt(event.target.id));

    request.onerror = function(event) 
    {
        console.log('Transaction failed');
    };

    request.onsuccess = function(event) 
   {
       console.log(request.result)
       if (request.result)
       {
            var nlikes = request.result.likes;
            console.log(request.result.text);
            nlikes + 1;

            //Increase the like of the post 
            var request = db.transaction(['posts'], 'readwrite')
                .objectStore('posts')
                .put({ id: parseInt(event.target.id),  likes: nlikes});

            request.onsuccess = function (event) 
            {
               console.log('The data has been updated successfully');
            };

            request.onerror = function (event) 
            {
                console.log('The data has been updated failed');

            //Add user like user to log
            }
       }     
   }
});

【问题讨论】:

  • 您熟悉基本的 javascript 错误吗?
  • 请启发我

标签: javascript local-storage indexeddb


【解决方案1】:

调试此错误时,熟悉它会有所帮助。此错误是一个基本的一般 JavaScript 错误,仅适用于 indexedDB。当您尝试访问未初始化对象的属性时,会出现错误 Uncaught TypeError: Cannot read property 'result' of undefined。本例中未初始化的对象为变量request,属性为result。因此,理解这个错误就是理解为什么 request 在您尝试访问其属性之一时未定义。

如果我自己不在浏览器中使用此代码,我不能完全确定为什么请求是未定义的。不过,我的第一个猜测可能会对您有所帮助。

稍后在函数var request = db.transaction... 行中再次声明相同的变量。这可能是函数前面未定义变量的原因。我会尝试解释原因。

当您使用var 关键字声明变量时,它并不总是出现在您声明它的位置。当 JavaScript 解释器评估您的代码时,它会对其进行一系列更改。发生的其中一种转换称为提升。使用var 声明的变量被提升到函数的开头,和/或在某些情况下甚至更早和函数范围之外。因此,这是违反直觉的,但解释器实际看到您的代码的方式看起来更像这样:

request.onsuccess = function(event) {
  var request = undefined;
  console.log(request.result);
  if(request.result) {
     ...;
     request = db.transaction...;
     ...;
  }
};

正如您在代码的这种变体中所见,在计算 console.log 表达式时,请求显然是未定义的。

如何解决这个错误?有几种方法。

首先,考虑使用 let/const 代替 var。 let/const 受范围限制。将范围想象为 {} 块的层次结构。如果您稍后将请求声明为let request = ...,那么这将避免提升问题,因为request 不会被提升到其封闭的 {} 块范围之外,因此永远不会按照评估顺序跳到祖先功能块范围的开头。

其次,考虑使用不同的变量。不要第二次执行var request = db.transaction...;,而是执行var request2 = db.transaction...;。现在,提升仍然发生,但这次变量request2 被提升到函数的顶部,它与request 没有标识符冲突。现在请求将在您调用 console.log 时定义。

第三,考虑使用一个 indexedDB 事务。您可以使用单个事务发出多个请求。从您的代码中并不明显,但看起来您没有充分的理由使用单独的事务。我能想到的唯一原因可能只是对 indexedDB 不熟悉。因此,学习如何在事务中发出多个请求会有所帮助。此外,如果这是一个问题,使用单个读写事务可能会比使用一个读取后一个写入更快,如果这可能是您使用多个 txns 的原因。

当您在一个 txn 上使用多个请求时,现在您可能会对 txn 何时完成感兴趣,而不是对单个请求何时完成感兴趣,因此,您甚至不再需要声明第二个请求对象,因此,不再会遇到吊装问题。

看起来像这样:

var txn = db.transaction(..., 'readwrite');
txn.oncomplete = function(event) {
  console.debug('txn completed');
};
txn.onerror = function(event) {
  console.debug('txn failed', event.target.error);
};

var store = txn.objectStore(...);
var request = store.get(...);
request.onsuccess = function(event) {
  //...;
  store.put(...);
  //...;
};

如果不是很明显,这里我只是重用 store,它是 IDBObjectStore 的一个实例,当我稍后调用 store.put 时,它仍然与创建它的事务相关联。

这三种不同方法中的任何一种都可能解决您的问题。

【讨论】:

    猜你喜欢
    • 2019-05-23
    • 1970-01-01
    • 2020-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多