在没有版本更改的情况下从 IndexedDB 阻塞事件中恢复
Recovering from IndexedDB blocked events without versionchange
我正在尝试针对 IndexedDB
库编写一些测试。
在这样做时,我故意通过调用 open()
对已打开的数据库使用更高版本来创建 blocked
事件。
虽然我可以通过在第一个 open()
期间在早期版本上设置的 versionchange
侦听器中关闭数据库来绕过阻塞,但出于测试目的,我想避免添加此 versionchange
监听器,而是让 blocked
事件被完全触发,这样我就可以确认我的 onblocked
监听器是否正常工作。
问题在于,在此阶段调用关闭数据库似乎无助于解除阻止,后续调用删除同一数据库也会收到 blocked
事件(在 Firefox 和 Chrome).因此,在执行此阻塞代码后,我无法继续进一步测试。
如果不使用先前添加的 versionchange
侦听器,是否无法从 blocked
事件中恢复?
代码如下:
var DB_NAME = 'test', DB_VERSION = 1, NEW_DB_VERSION = 2;
indexedDB.deleteDatabase(DB_NAME);
var data = [{
firstName: 'Brett',
lastName: 'Zamir',
age: 43
}, {
firstName: 'Jane',
lastName: 'Doe',
age: 40
}, {
firstName: 'Bob',
lastName: 'Doe',
age: 42
}];
var req = indexedDB.open(DB_NAME, DB_VERSION);
req.onerror = function (evt) {
console.error("openDb:", evt.target.errorCode);
};
req.onsuccess = function (evt) {
var db = this.result;
};
req.onupgradeneeded = function (e) {
var db = e.target.result;
var os = db.createObjectStore('test', {
keyPath: 'id',
autoIncrement: true
});
os.transaction.oncomplete = function () {
var testTx = db.transaction('test', 'readwrite');
testTx.oncomplete = function () {
console.log('storage completed');
fireBlockedEvent(db);
};
var testStore = testTx.objectStore('test');
for (var i in data) {
testStore.add(data[i]);
}
};
};
function fireBlockedEvent (db) {
var req = indexedDB.open(DB_NAME, NEW_DB_VERSION);
req.onblocked = function () {
console.log('blocked');
db.close();
var req = indexedDB.deleteDatabase(DB_NAME);
req.onsuccess = function () {
console.log('we ok');
};
req.onblocked = function () {
console.log('still blocked');
};
};
}
您打开了两个连接,但只关闭了一个。
在 fireBlockedEvent
中,您将关闭通过 open(DB_NAME, DB_VERSION)
打开的连接(作为 db
传入)。但是在调用 deleteDatabase()
.
之前,您永远不会关闭通过 open(DB_NAME, NEW_DB_VERSION)
在 fireBlockedEvent
本身中打开的连接
删除请求将被阻止,直到所有连接都关闭。
由于您正在编写测试代码,所以很难在不改变语义的情况下提出具体的修复建议,但这行得通:
function fireBlockedEvent (db) {
var req = indexedDB.open(DB_NAME, NEW_DB_VERSION);
req.onblocked = function () {
console.log('blocked');
// close the blocking connection:
db.close();
};
req.onsuccess = function (e) {
// close the formerly blocked connection:
e.target.result.close();
var req = indexedDB.deleteDatabase(DB_NAME);
req.onsuccess = function () {
console.log('we ok');
};
req.onblocked = function () {
console.log('still blocked');
};
};
}
我正在尝试针对 IndexedDB
库编写一些测试。
在这样做时,我故意通过调用 open()
对已打开的数据库使用更高版本来创建 blocked
事件。
虽然我可以通过在第一个 open()
期间在早期版本上设置的 versionchange
侦听器中关闭数据库来绕过阻塞,但出于测试目的,我想避免添加此 versionchange
监听器,而是让 blocked
事件被完全触发,这样我就可以确认我的 onblocked
监听器是否正常工作。
问题在于,在此阶段调用关闭数据库似乎无助于解除阻止,后续调用删除同一数据库也会收到 blocked
事件(在 Firefox 和 Chrome).因此,在执行此阻塞代码后,我无法继续进一步测试。
如果不使用先前添加的 versionchange
侦听器,是否无法从 blocked
事件中恢复?
代码如下:
var DB_NAME = 'test', DB_VERSION = 1, NEW_DB_VERSION = 2;
indexedDB.deleteDatabase(DB_NAME);
var data = [{
firstName: 'Brett',
lastName: 'Zamir',
age: 43
}, {
firstName: 'Jane',
lastName: 'Doe',
age: 40
}, {
firstName: 'Bob',
lastName: 'Doe',
age: 42
}];
var req = indexedDB.open(DB_NAME, DB_VERSION);
req.onerror = function (evt) {
console.error("openDb:", evt.target.errorCode);
};
req.onsuccess = function (evt) {
var db = this.result;
};
req.onupgradeneeded = function (e) {
var db = e.target.result;
var os = db.createObjectStore('test', {
keyPath: 'id',
autoIncrement: true
});
os.transaction.oncomplete = function () {
var testTx = db.transaction('test', 'readwrite');
testTx.oncomplete = function () {
console.log('storage completed');
fireBlockedEvent(db);
};
var testStore = testTx.objectStore('test');
for (var i in data) {
testStore.add(data[i]);
}
};
};
function fireBlockedEvent (db) {
var req = indexedDB.open(DB_NAME, NEW_DB_VERSION);
req.onblocked = function () {
console.log('blocked');
db.close();
var req = indexedDB.deleteDatabase(DB_NAME);
req.onsuccess = function () {
console.log('we ok');
};
req.onblocked = function () {
console.log('still blocked');
};
};
}
您打开了两个连接,但只关闭了一个。
在 fireBlockedEvent
中,您将关闭通过 open(DB_NAME, DB_VERSION)
打开的连接(作为 db
传入)。但是在调用 deleteDatabase()
.
open(DB_NAME, NEW_DB_VERSION)
在 fireBlockedEvent
本身中打开的连接
删除请求将被阻止,直到所有连接都关闭。
由于您正在编写测试代码,所以很难在不改变语义的情况下提出具体的修复建议,但这行得通:
function fireBlockedEvent (db) {
var req = indexedDB.open(DB_NAME, NEW_DB_VERSION);
req.onblocked = function () {
console.log('blocked');
// close the blocking connection:
db.close();
};
req.onsuccess = function (e) {
// close the formerly blocked connection:
e.target.result.close();
var req = indexedDB.deleteDatabase(DB_NAME);
req.onsuccess = function () {
console.log('we ok');
};
req.onblocked = function () {
console.log('still blocked');
};
};
}