mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-01 05:58:19 -06:00
Web: IndexedDB puts and deletes resolve when their transaction commits (#1242)
This commit is contained in:
@@ -57,6 +57,26 @@ function req(r) {
|
||||
return new Promise((res, rej) => { r.onsuccess = () => res(r.result); r.onerror = () => rej(r.error); });
|
||||
}
|
||||
|
||||
// Run `op` on `store` in a readwrite transaction of its own; resolves once the transaction has
|
||||
// committed. A request's success doesn't mean the write is stored: the transaction can still
|
||||
// abort afterwards (quota at commit, the browser closing), rolling it back, and a write
|
||||
// reported as saved then is never retried (#1242). A failed request aborts the transaction
|
||||
// with its error; an explicit abort leaves no error, hence the AbortError.
|
||||
function write(db, store, op) {
|
||||
return new Promise((res, rej) => {
|
||||
let tx = null;
|
||||
try {
|
||||
tx = db.transaction(store, "readwrite");
|
||||
tx.oncomplete = () => res();
|
||||
tx.onabort = () => rej(tx.error ?? new DOMException("the storage transaction was aborted", "AbortError"));
|
||||
op(tx.objectStore(store));
|
||||
} catch (e) {
|
||||
try { tx?.abort(); } catch {}
|
||||
rej(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function idb() {
|
||||
if (!self.indexedDB) throw new Error("no IndexedDB");
|
||||
const open = indexedDB.open(DB, 1);
|
||||
@@ -70,10 +90,10 @@ async function idb() {
|
||||
return all.map((r) => ({ key: r.key, data: new Uint8Array(r.data), modified: r.modified }));
|
||||
},
|
||||
async put(key, data, modified) {
|
||||
await req(tx("readwrite").put({ key, data: data.slice().buffer, modified }));
|
||||
await write(db, STORE, (s) => s.put({ key, data: data.slice().buffer, modified }));
|
||||
},
|
||||
async del(key) {
|
||||
await req(tx("readwrite").delete(key));
|
||||
await write(db, STORE, (s) => s.delete(key));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user