我有以下代码。它在 Firefox 上完美运行,但在 Chrome 上不起作用。但如果我打开开发者工具,它甚至可以在 chrome 上运行。可能是什么问题?
function resetDatabase() {
let request = indexedDB.deleteDatabase("CityDatabase4");
request.onsuccess = function() {
const cityVersion = 0;
localStorage.setItem('cityVersion', cityVersion);
window.location.reload();
};
request.onerror = function() {
};
request.onblocked = function() {
};
}
该问题可能源于 IndexedDB 行为的两个关键方面
连接处理。根据规范,删除数据库时,必须首先关闭所有现有连接。如果在尝试删除数据库时其他连接仍然打开,则会触发
onblocked
事件。
Chrome 的行为。 Chrome 可能会维护一些不立即可见的后台连接,这就是为什么打开 DevTools(可以强制连接清理)使其起作用。
这是代码的更正版本,它应该在浏览器中一致地工作:
function resetDatabase() {
// First, close any existing connections
const DBOpenRequest = indexedDB.open("CityDatabase4");
DBOpenRequest.onsuccess = function(event) {
const db = event.target.result;
db.close();
// Now proceed with deletion
let request = indexedDB.deleteDatabase("CityDatabase4");
request.onsuccess = function() {
const cityVersion = 0;
localStorage.setItem('cityVersion', cityVersion);
window.location.reload();
};
request.onerror = function(event) {
console.error("Error deleting database:", event.target.error);
};
request.onblocked = function(event) {
console.log("Database deletion blocked");
};
};
}
onblocked
事件规格说明:
“如果 openConnections 中的任何连接仍未关闭,则将任务排队以根据请求使用数据库版本和 null 触发名为“blocked”的版本更改事件。”
*了解更多信息: https://w3c.github.io/IndexedDB/#opening
这就是为什么添加适当的连接清理有助于确保跨浏览器的一致行为。
其他建议:
function resetDatabase() {
return new Promise((resolve, reject) => {
const DBOpenRequest = indexedDB.open("CityDatabase4");
const timeout = setTimeout(() => {
reject(new Error("Database operation timed out"));
}, 5000); // 5 second timeout
DBOpenRequest.onsuccess = function(event) {
const db = event.target.result;
db.close();
let request = indexedDB.deleteDatabase("CityDatabase4");
request.onsuccess = function() {
clearTimeout(timeout);
const cityVersion = 0;
localStorage.setItem('cityVersion', cityVersion);
resolve();
window.location.reload();
};
request.onerror = function(event) {
clearTimeout(timeout);
reject(event.target.error);
};
request.onblocked = function(event) {
clearTimeout(timeout);
reject(new Error("Database deletion blocked"));
};
};
DBOpenRequest.onerror = function(event) {
clearTimeout(timeout);
reject(event.target.error);
};
});
}
versionchange
事件侦听器来处理可能从另一个选项卡中删除数据库的情况:db.onversionchange = function() {
db.close();
};
这应该可以在不同的浏览器和场景中提供更可靠的行为。