当在这段代码中时,我收到错误‘:Cannot read property’TypeError‘of null’
remoteDB.indexedDB.addAdmins = function() {
var db = remoteDB.indexedDB.db;
var trans = db.transaction("students", "readwrite");
var request = trans.objectStore("administrators");
/*
this section edited out since the failure is on line 3
*/
request.onsuccess = function(e) {
console.log("success Adding: ", e);
};
request.onerror = function(e) {
console.log(e.value);
};
};
发布于 2014-06-17 20:36:25
remoteDB.indexedDB.db为空。这似乎是一个全局变量引用。为了创建事务,必须定义变量,而不是null和open。
indexedDB是异步的。不能保证当您打开到indexedDB的连接并将该连接的句柄保存在一个全局变量中时,该变量仍然是定义的,而不是null,并在以后从另一个异步函数的上下文中打开。
如果您立即打开一个事务,它有时会起作用。有时,db连接仍然存在。但这并不是有保证的。如果数据库连接上没有打开的事务,则浏览器将在之后的某个时间关闭该连接。
看见
出现这种错误的部分原因通常是程序员对异步javascript不熟悉。这不是批评,这似乎是一种常见的模式。为了避免将来出现错误,我建议花一些时间学习异步javascript。
例如,在尝试使用indexedDB之前,请了解以下内容是如何工作的(或者更确切地说,为什么它不能按预期工作):
var db;
function setDB() {
db = 123;
}
setTimeout(setDB, 10);
console.log('Got a db variable! %s', db);
要真正做到这一点,在stackoverflow上有成千上万的其他问题以及网上有洞察力的文章和指南是多余的,但这里有一个极端的速成课程。indexedDB.open是一个异步(异步)函数。形容词异步的意思很多。异步函数的行为与同步函数的行为截然不同。新的javascript程序员通常只学会同步编程。因此,你自然不会明白为什么在同步代码中调用异步函数不起作用。同步示例:
var a = 1;
var b = 2;
function sum(arg1, arg2) { return arg1 + arg2 }
var abSum = sum(a,b);
console.log('The sum of a + b is %s', abSum);
您知道,b=2是在a=1之后执行的,sum=a+b是在b之后执行的。这些语句是按您编写的顺序依次执行的。您知道,如果您尝试将第4行放在上面的第1行之前,它将不起作用,因为a和b还没有值。在同步代码中,您知道函数sum返回一个值。它会立即返回它。因此,您知道调用abSum (a,b)会立即将返回值赋给sum。
异步代码的工作方式截然不同。通常,异步函数不会返回所需的值。通常将一个函数(称为回调函数)传递给该函数。异步函数只是在某种程度上保证了它将在稍后调用回调。它不返回要使用的内容。
var a = 1;
var b = 2;
function asyncSum(arg1,arg2,calledWhenFinished) {
var sum = arg1+arg2;
calledWhenFinished(sum);
return 'asyncSumFinished and called the callback';
}
// The following DOES NOT work as expected
var theResultOfSum = asyncSum(a,b, function(sum) {
console.log('finished. The um is %s', theResultOfSum);
});
// The following DOES work as expected
asyncSum(a,b, function(sum) {
console.log('The sum is %s', sum);
});
请注意,在工作示例中,我并不关心asyncSum返回什么。毕竟,它并不返回sum,它只是返回一个字符串,说明它已经完成了。现在,让我们做一些更真实的异步操作。
function moreGenuineAsyncSum(a,b, callback) {
setTimeout(function() {
var sum = a + b;
console.log('The sum is %s', sum);
callback(sum);
}, 100);
console.log('Requested the sum to be calculated');
return 'Hey, I scheduled the callback function to execute in 100ms';
}
在这里,我真的不关心moreGenuineAsyncSum的返回值。事实上,它一文不值。它只是一个能表达某些东西的字符串。还要注意哪个console.log调用首先被执行。后一行在前一行之前执行。杂乱无序。打乱了它的书写顺序。为什么会这样呢?因为这就是异步函数所做的,所以它们会在以后的某个时间点执行某些操作。
indexedDB.open是一个异步函数。它返回一个IDBOpenRequest对象,这是一种请求对象。大多数indexedDB函数都是异步的,并且返回请求对象。请求对象没有值。它们将回调作为属性。因此:
var dbRequest = indexedDB.open('mydb',1);
dbRequest.onsuccess = function(event) {
// This gets called later. The following are all viable ways to get the IDBDatabase
// object INSIDE THE BLOCK OF THIS FUNCTION ONLY. Any one of the following 3 lines
// works exactly the same way.
var db = this.result;
var db = dbRequest.result;
var db = event.target.result;
console.log('Got a db connection! It is %s', db);
// Now, INSIDE THE BLOCK OF THIS FUNCTION ONLY, do something:
var myTransaction = db.transaction('myObjectStore','readwrite');
var myObjectStore = myTransaction.objectStore('myObjectStore');
// etc.
};
在我写整本书之前总结一下,重点放在上面的块注释里面。在块内部,保证'db‘变量在那里,并且是开放的,并且是被定义的,并且不为空。在块之外,db变量不存在。
所以你可能会说,这使得使用indexedDB非常烦人。你说得对,这很烦人。为了让它对你不那么烦人,你可以学习promises。或者你可以像函数一样编写回调函数。或者,您可以使用处理回调地狱的无数设计模式中的一个。有很多。一种是使用像EventTarget这样的模式及其与DOM的关系。
https://stackoverflow.com/questions/24256202
复制相似问题