IndexedDB 读取在写入完成之前完成

IndexedDB read completing before write finishes

我正在流式传输日志文件,当某个日志条目被捕获时(我们称之为事件 A),我将它们写入 IndexedDB。当另一个特定的日志条目被捕获时(比如,事件 B),我在对象存储中搜索匹配的事件 A 条目。

只要事件 A 和事件 B 不连续发生,这就可以正常工作。如果它们连续发生(假设事件 A 被写入日志文件,然后事件 B 立即写入),则找不到事件 A 的条目。

我尝试在 "readwrite" 模式下读取事件 A,但这没有用 - 这是出乎意料的,因为我认为以读写方式打开意味着它不会尝试 运行 交易,直到事件 A 已完成。

我正在考虑实施的一个解决方案是跟踪每笔交易,并且仅在所有交易都已完成时才启动搜索 - 但对于我认为很常见的事情似乎需要付出很多努力?

addEntry(store: string, entry: any): Promise<boolean> {
    return new Promise<boolean>((resolve, reject) => {
        this.dbPromise.then(db => {
            let transaction = db.transaction(store, "readwrite");

            transaction.oncomplete = (evt: any) => {
                resolve(true);
            }

            transaction.onerror = (err: any) => {
                this.logger.error({
                    originalError: err,
                    message: 'transaction error',
                    data: {
                        store,
                        entry
                    }
                });
                reject(err);
            }

            transaction.onabort = (evt: any) => {
                this.logger.error({
                    originalError: evt,
                    message: 'transaction aborted',
                    data: {
                        store,
                        entry
                    }
                })
                reject(evt);
            }

            let objectStore = transaction.objectStore(store);

            let request = objectStore.add(entry);

            request.onerror = (err) => {
                console.dir(err);
            }
        })
        .catch(err=>{
            this.logger.error({
                originalError: err,
                message: 'journalDBService.addEntry error',
                data: {
                    store,
                    entry
                }
            });
        })
    })
}

getEntry(store: string, key:any): Promise<any> {
    return new Promise<any>((resolve,reject)=>{
        this.dbPromise.then(db=>{
            let transaction = db.transaction(store, "readonly");
            let objectStore = transaction.objectStore(store);
            let request = objectStore.get(key)

            request.onsuccess = (evt) => {
                resolve((<IDBRequest>evt.target).result);
            }

            request.onerror = (err) => {
                this.logger.error({
                    originalError: err,
                    message: 'journalDBService.getEntry request error',
                    data: {
                        store,
                        key
                    }
                });
            }
        })
        .catch(err=>{
            let report = {
                originalError: err,
                message: 'journalDBService.addEntry error',
                data: {
                    store,
                    key
                }
            };
        })
    })
}

编辑:下面的实际违规代码

this.journalDB.getEntry(journal.JournalEvents.missionAccepted, (<journal.MissionAccepted>data).MissionID).then(result => {
if (!result) {
    this.journalDB.addEntry(journal.JournalEvents.missionAccepted, data)
        .catch(err => {
            let report = {
                originalError: err,
                message: 'journalService.handleEvent error',
                data
            }
            this.logger.error(report);
        })
}

})

索引数据库要求在 "readwrite" 具有重叠范围的事务之后安排的 "readonly" 事务不会 运行 直到 "readwrite" 事务完成,这样才能看到结果的写。所以是的,你的期望是正确的。

所以...可能性是:

  • 您正在处理一个错误的实现(哪个浏览器?您可以独立重现这个吗?)
  • 交易没有按照您期望的顺序开始;您可以记录 db.transaction 次通话并验证订单吗? (即可能 dbPromise.then 处理程序未按您期望的顺序 运行 宁)
  • 还有其他一些逻辑错误,例如密钥不正确,因此看不到该值

你能缩小是哪一个吗?