我发现,如果我
load
在间接加载模块的顶层打开 IndexedDB,则 await
事件不会触发。
如果我删除
await
,则会按预期调用 load
处理程序。
如果我保留 await
但用虚拟承诺替换 openDB
调用(如 Promise.resolve(42)
),则将按预期调用 load
处理程序。
发生了什么事,我该如何调试?
index.html:
...
<script type="module" src="js/ui_index.js" type="javascript/module"></script>
...
(它还包含一个导入映射,因此所有导入都可以正常工作)
ui_index.js:
import * as db from "database";
...
window.addEventListener('load', () => console.log('onload'));
console.log('ui');
数据库.js:
import { openDB } from "lib/idb";
// ↓↓↓↓↓ *** THIS AWAIT ***
const db = await openDB("my-database-name", 4, {
upgrade(db, old_ver, new_ver, tx) {
console.log(`db.upgrade ${old_ver}→${new_ver}`);
}
}
console.log('db:', db);
上面的
idb
模块是 Jake Archibald 开发的基于 promises 的 IndexedDB 包装器。
控制台输出带有
await
:
db.upgrade 4→5
db: Proxy { <target>: IDBDatabase, <handler>: {…} }
ui
控制台输出没有
await
:
db: Promise { <state>: "pending" }
ui
onload
db.upgrade 5→6
(当然,仅当我在
db.upgrade
调用中增加数据库版本时,openDB
行才会出现。它不会影响 onload
行为)。
我正在 Firefox 120 中测试此功能,尚未尝试其他浏览器;我正在构建一个供内部使用的小型网络应用程序,该应用程序只能与 Firefox 一起使用。
我的猜测是,您在脚本主体中执行等待,而不是声明执行等待的函数,这推迟了 onload 事件侦听器的附加,我相信它仍然会被触发,但在附加事件侦听器之前。
我可以建议你这样的事情吗:
数据库.js:
import { openDB } from "lib/idb";
export default async function open() {
const db = await openDB("my-database-name", 4, {
upgrade(db, old_ver, new_ver, tx) {
console.log(`db.upgrade ${old_ver}→${new_ver}`);
}
}
console.log('db:', db);
}
ui_index.js:
import open from "database";
window.addEventListener('load', () => console.log('onload'));
console.log('ui');
open();