重复相同请求时 IndexedDB 变慢
IndexedDB slow when repeating the same request
我正在使用 TypeScript
和 Observables
在 AngularJS 2
中实现 IndexedDB
。我发现打开 IndexedDB
数据库然后获取 500 条记录只用了不到一秒钟。但是,在该数据库连接仍处于打开状态的情况下,再次获取相同的数据大约需要 110 秒。我尝试了各种选项,包括游标来检索所有结果相同的数据。这家店也只有4000条左右的记录。
我在下面包含了一些示例代码来尝试说明我正在尝试做什么。正在执行 OfflineService.test()
作为入口点。
export class OfflineService {
constructor(private indexedDbService: IndexedDbService) {
}
test(): void {
this.indexedDbService.openDb()
.subscribe((open: boolean) => {
if (!open) {
// IndexedDB not supported
return;
}
this.indexedDbService.getObjectsById("items", 1, 500)
.subscribe((results: any[]) => {
// results returned in < 1 second
// retrieve again
this.indexedDbService.getObjectsById("items", 1, 500)
.subscribe((results: any[]) => {
// results returned in around 110 seconds
});
});
});
}
}
export class IndexedDbService {
private db: any;
openDb(): Observable<boolean> {
return Observable.create((observer: any) => {
try {
if (this.db) {
observer.next(true);
observer.complete();
return;
}
const request = indexedDB.open("testDb", 1);
request.onupgradeneeded = (event: any) => {
event.currentTarget.result.createObjectStore("items", { keyPath: "Id", autoIncrement: false });
};
request.onsuccess = () => {
this.db = request.result;
observer.next(true);
observer.complete();
};
request.onerror = () => {
observer.next(false);
observer.complete();
};
} catch (err) {
observer.next(false);
observer.complete();
}
});
}
getObjectsById(storeName: string, lowerId: number, upperId: number): Observable<any> {
return Observable.create((observer: any) => {
try {
const results: any[] = [];
const store = this.getObjectStore(storeName, false);
const request = store.openCursor(IDBKeyRange.bound(lowerId, upperId));
request.onsuccess = () => {
var cursor = request.result;
if (cursor) {
results.push(cursor.value);
cursor.continue();
} else {
observer.next(results);
observer.complete();
}
};
request.onerror = (event) => {
observer.error(Error(event.target.errorCode));
};
} catch (err) {
observer.error(err);
}
});
}
private getObjectStore(storeName: string, writable: boolean): any {
const transaction = this.db.transaction(storeName, writable ? "readwrite" : "readonly");
return transaction.objectStore(storeName);
}
}
我终于想通了,这与 IndexedDB
或 Observables
没有任何关系。只是在加载第一组结果后,对 IndexedDB
的第二次调用变慢了,这仅仅是因为使用了更多的内存。在进行第二次调用之前清除原始结果修复了性能问题。
我正在使用 TypeScript
和 Observables
在 AngularJS 2
中实现 IndexedDB
。我发现打开 IndexedDB
数据库然后获取 500 条记录只用了不到一秒钟。但是,在该数据库连接仍处于打开状态的情况下,再次获取相同的数据大约需要 110 秒。我尝试了各种选项,包括游标来检索所有结果相同的数据。这家店也只有4000条左右的记录。
我在下面包含了一些示例代码来尝试说明我正在尝试做什么。正在执行 OfflineService.test()
作为入口点。
export class OfflineService {
constructor(private indexedDbService: IndexedDbService) {
}
test(): void {
this.indexedDbService.openDb()
.subscribe((open: boolean) => {
if (!open) {
// IndexedDB not supported
return;
}
this.indexedDbService.getObjectsById("items", 1, 500)
.subscribe((results: any[]) => {
// results returned in < 1 second
// retrieve again
this.indexedDbService.getObjectsById("items", 1, 500)
.subscribe((results: any[]) => {
// results returned in around 110 seconds
});
});
});
}
}
export class IndexedDbService {
private db: any;
openDb(): Observable<boolean> {
return Observable.create((observer: any) => {
try {
if (this.db) {
observer.next(true);
observer.complete();
return;
}
const request = indexedDB.open("testDb", 1);
request.onupgradeneeded = (event: any) => {
event.currentTarget.result.createObjectStore("items", { keyPath: "Id", autoIncrement: false });
};
request.onsuccess = () => {
this.db = request.result;
observer.next(true);
observer.complete();
};
request.onerror = () => {
observer.next(false);
observer.complete();
};
} catch (err) {
observer.next(false);
observer.complete();
}
});
}
getObjectsById(storeName: string, lowerId: number, upperId: number): Observable<any> {
return Observable.create((observer: any) => {
try {
const results: any[] = [];
const store = this.getObjectStore(storeName, false);
const request = store.openCursor(IDBKeyRange.bound(lowerId, upperId));
request.onsuccess = () => {
var cursor = request.result;
if (cursor) {
results.push(cursor.value);
cursor.continue();
} else {
observer.next(results);
observer.complete();
}
};
request.onerror = (event) => {
observer.error(Error(event.target.errorCode));
};
} catch (err) {
observer.error(err);
}
});
}
private getObjectStore(storeName: string, writable: boolean): any {
const transaction = this.db.transaction(storeName, writable ? "readwrite" : "readonly");
return transaction.objectStore(storeName);
}
}
我终于想通了,这与 IndexedDB
或 Observables
没有任何关系。只是在加载第一组结果后,对 IndexedDB
的第二次调用变慢了,这仅仅是因为使用了更多的内存。在进行第二次调用之前清除原始结果修复了性能问题。