我正在尝试从IndexedDB数据库获得喜欢的数字。但是,我收到此错误
未捕获到的TypeError:无法读取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
}
}
}
});
答案 0 :(得分:1)
在调试此错误时,熟悉它会有所帮助。此错误是基本的常规JavaScript错误,不适用于仅indexedDB。当您尝试访问未初始化对象的属性时,发生错误Uncaught TypeError: Cannot read property 'result' of undefined
。在这种情况下,未初始化的对象是变量request
,而属性是result
。因此,了解此错误只是了解为什么在尝试访问request
的属性之一时未定义var request = db.transaction...
。
我不完全确定为什么未在浏览器中亲自处理此代码就无法定义请求的原因。但是,我有一个初步的猜测,也许会对您有所帮助。
稍后您将在函数var
中的函数中再次声明相同的变量。这可能是在函数的早期未定义变量的原因。我将尝试解释原因。
使用var
关键字声明变量时,它并不总是在声明它的地方发生。当JavaScript解释器评估您的代码时,它将对其进行一系列更改。发生的一种转换称为提升。用request.onsuccess = function(event) {
var request = undefined;
console.log(request.result);
if(request.result) {
...;
request = db.transaction...;
...;
}
};
声明的变量被提升到函数的开始,和/或在某些情况下甚至早于函数范围。因此,这是违反直觉的,但是解释器实际看到您的代码的方式看起来像这样:
let request = ...
正如您在代码的这种变体中所看到的那样,在评估console.log表达式时,请求显然是未定义的。
如何解决此错误?有几种方法。
首先,考虑使用let / const代替var。 let / const受范围限制。将范围想象为{}块的层次结构。如果以后将请求声明为request
,则可以避免提升问题,因为var request = db.transaction...;
不会被提升到其封闭的{}块范围之外,因此永远不会以评估顺序跳到祖先函数的开始封锁范围。
第二,考虑使用其他变量。不用第二次var request2 = db.transaction...;
,而是request2
。现在,仍然发生提升,但是这次变量request
被提升到函数的顶部,该变量与console.log
没有标识符冲突。现在,请求将在您致电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(...);
//...;
};
时定义。
第三,考虑使用一个indexedDB事务。您可以使用一个事务发出多个请求。从您的代码中看不出来,但是看起来没有充分的理由让您使用单独的事务。我能想到的唯一原因可能是对indexedDB缺乏了解。因此,这将有助于学习如何在事务中发出多个请求。另外,如果您担心的话,使用单个读写事务可能比使用先读后写的速度要快,如果这可能是您造成多个txns的原因。
当您在一个txn上使用多个请求时,现在您可能会对txn的完成时间感兴趣,而不是对单个请求的完成时间感兴趣,因此,您甚至不需要声明第二个请求对象,因此,不再会首先遇到吊装问题。
它看起来像这样:
store.put
在不太明显的情况下,这里我只是重用store,它是IDBObjectStore的实例,仍然与我稍后调用returnString
时在其中创建它的事务绑定。
这三种不同方法中的任何一种都可能解决您的问题。