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
处理程序未按您期望的顺序 运行 宁)
- 还有其他一些逻辑错误,例如密钥不正确,因此看不到该值
你能缩小是哪一个吗?
我正在流式传输日志文件,当某个日志条目被捕获时(我们称之为事件 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
处理程序未按您期望的顺序 运行 宁) - 还有其他一些逻辑错误,例如密钥不正确,因此看不到该值
你能缩小是哪一个吗?