IndexedDB使用
使用場景
- 具體使用場景:
存儲用戶瀏覽記錄。
適合的使用場景:
- 處於安全性考慮,數據不能存儲到服務器端。
- 數據爲結構性數據或者數據量較大,不適合使用cookies。
- 希望數據不隨着客戶清理緩存而刪除。此時我們一定一定要設計好清理瀏覽器端數據的時機。
相關站點
ps:那麼多好的資料了,爲什麼還寫博客?
1. 做筆記;
2. 我用的Angular2,語法糖是ES6的啊。
代碼段
代碼段來自項目,當然是底層的與項目無關。這部分代碼大部分是已有的,來自一個已經離開項目的同事,我寫了一部分。在此我只是記錄下而已。
// 項目使用的是Angular2,這是一個service。有關Angular2的寫法我不做說明。
import { Injectable } from '@angular/core';
@Injectable()
export class WorkIndexedDBService {
// 聲明一些屬性,name:數據庫名,version:數據庫版本
// name和version發生變化,瀏覽器就會重新建一個新的indexedDB
private name: string = 'test-docView';
private version: number = 1;
private db: any = null;
constructor() { }
// 打開並創建數據庫
public open(): Promise<any> {
return new Promise<any>((resolve, reject) => {
// 打開indexedDB
let req = indexedDB.open(this.name, this.version);
// 打開DB成功後的回調
req.onsuccess = function(event) {
this.db = event.target.result;
resolve();
}.bind(this);
// 此處說明.bind(this),是爲了把當前類的屬性和方法傳入req.onsuccess的這個function裏。即:.bind(this)的this是指本類WorkIndexedDBService
// 打開DB失敗後的回調
req.onerror = reject;
// 打開新的數據庫時,會回調此函數,改變name和version均會建立新的DB,所以都會發生此回調。
req.onupgradeneeded = function(event) {
// 如果版本升級要記得刪除舊的數據庫表再建立新的。
this.db = event.target.result;
let storeNames = this.db.objectStoreNames;
if (storeNames && storeNames.length > 0) {
for (let i = 0 ; i < storeNames.length ; i++) {
this.db.deleteObjectStore(storeNames[i]);
console.log('deleteObjectStore', storeNames[i]);
}
}
// 創建數據庫表
this.createViewDB();
}.bind(this);
});
}
// 關閉數據庫
public close(): void {
this.db.close();
}
// 刪除數據庫
public deleteDB(): Promise<any> {
return new Promise<any>((resolve, reject) => {
// 先關閉連接再刪
this.close();
let req = indexedDB.deleteDatabase(this.name);
req.onsuccess = function(event) {
this.db = null;
resolve();
}.bind(this);
req.onerror = reject;
});
}
// 添加數據
// 注意:使用事務來做操作比較快。
public insert(
storeName: string,
data: any
): Promise<any> {
return new Promise<any>((resolve, reject) => {
let transaction = this.db.transaction(storeName, 'readwrite');
let store = transaction.objectStore(storeName);
let req = store.add(data);
req.onsuccess = function(event) {
resolve(req.result);
};
req.onerror = reject;
});
}
// 批量添加數據
public batchInsert(
storeName: string,
data: any[]
): Promise<any> {
if (!data || data.length === 0) {
return Promise.resolve();
}
let transaction = this.db.transaction(storeName, 'readwrite');
let store = transaction.objectStore(storeName);
return new Promise<null>((resolve, reject) => {
data.forEach(row =>
store.add(row);
});
transaction.oncomplete = resolve;
transaction.onerror = reject;
})
.catch((error) => {
console.error('添加' + storeName + '表數據失敗', error);
return Promise.reject(error);
});
}
// 刪除數據
public workdelete(
storeName: string,
keyValue: any
): Promise<any> {
return new Promise<any>((resolve, reject) => {
let transaction = this.db.transaction(storeName, 'readwrite');
let store = transaction.objectStore(storeName);
let req = store.delete(keyValue);
req.onsuccess = resolve;
req.onerror = reject;
});
}
// 清楚全部數據
public clearAllData(): Promise<any> {
let storeNameList: Array<string> = new Array<string>();
let storeNames = this.db.objectStoreNames;
if (storeNames && storeNames.length > 0) {
for (let i = 0 ; i < storeNames.length ; i++) {
storeNameList.push(storeNames[i]);
}
}
return Promise.all(
storeNameList.map((storeName) => {
return this.clear(storeName);
})
);
}
// 清空數據
public clear(
storeName: string
): Promise<any> {
return new Promise<any>((resolve, reject) => {
let transaction = this.db.transaction(storeName, 'readwrite');
let store = transaction.objectStore(storeName);
let req = store.clear();
req.onsuccess = resolve;
req.onerror = reject;
});
}
// 更新數據
public update(
storeName: string,
data: any
): Promise<any> {
return new Promise<any>((resolve, reject) => {
let transaction = this.db.transaction(storeName, 'readwrite');
let store = transaction.objectStore(storeName);
let req = store.put(data);
req.onsuccess = resolve;
req.onerror = reject;
});
}
// 根據Key取得數據
public selectByKey(
storeName: string,
keyValue: any
): Promise<any> {
return new Promise<any>((resolve, reject) => {
let transaction = this.db.transaction(storeName, 'readonly');
let store = transaction.objectStore(storeName);
let req = store.get(keyValue);
req.onsuccess = function() {
resolve(req.result);
}
req.onerror = reject;
});
}
// 根據索引取得數據
public selectByIndex(
storeName: string,
indexName: string,
indexValue: any
): Promise<any[]> {
return new Promise<any[]>((resolve, reject) => {
let transaction = this.db.transaction(storeName, 'readonly');
let store = transaction.objectStore(storeName);
let index = store.index(indexName);
let req = index.openCursor(indexValue);
let result: any[] = new Array<any>();
req.onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
result.push(cursor.value);
cursor.continue();
} else {
resolve(result);
}
}
req.onerror = reject;
});
}
// 批量合併數據
public batchMerge(
storeName: string,
data: any[],
delFlagColName?: string,
delFlagColName2?: string
): Promise<any> {
if (!data || data.length === 0) {
return Promise.resolve();
}
let transaction = this.db.transaction(storeName, 'readwrite');
let store = transaction.objectStore(storeName);
return new Promise<null>((resolve, reject) => {
data.forEach(row => {
let keyPath = store.keyPath;
let keyValue;
if (typeof keyPath === 'string') {
keyValue = row[keyPath];
} else {
keyValue = new Array();
keyPath.forEach(key => {
keyValue.push(row[key]);
});
}
store.delete(keyValue);
} else {
store.put(row);
}
});
transaction.oncomplete = resolve;
transaction.onerror = reject;
})
.catch((error) => {
console.error('更新' + storeName + '表數據失敗', error);
return Promise.reject(error);
});
}
// 數據庫初始化處理
private createDB(): void {
this.createConfigInfo();
this.createStoreUserInfo();
this.createStoreOrgInfo();
this.createStoreUserOrgInfo();
}
// 創建系統配置表及索引
private createConfigInfo(): void {
let store = this.db.createObjectStore(
'ConfigInfo',
{keyPath: 'key'}
);
}
// 創建用戶表及索引
private createStoreUserInfo(): void {
let store = this.db.createObjectStore(
'UserInfo',
{keyPath: 'userId'}
);
}
// 創建組織表及索引
private createStoreOrgInfo(): void {
let store = this.db.createObjectStore(
'OrgInfo',
{keyPath: 'orgId'}
);
store.createIndex(
'parentOrgIdIndex',
['parentOrgId', 'displayOrder'],
{unique: false}
);
}
// 創建組織表及索引
private createStoreUserOrgInfo(): void {
let store = this.db.createObjectStore(
'UserOrgInfo',
// S zhuruifei 2017-08-14 通訊錄數據結構變更
{keyPath: 'personRoleId'}
// E zhuruifei 2017-08-14 通訊錄數據結構變更
);
store.createIndex(
'orgIdIndex',
'orgId',
{unique: false}
);
}
// 創建稿件瀏覽記錄表
private createViewDB(): void{
let store = this.db.createObjectStore(
'viewedDoc',
{keyPath: 'docId'}
);
store.createIndex(
'viewedDoc',
'docId',
{unique: true}
);
}
// 批量查詢稿件瀏覽信息
judgeIfWatched(
storeName: string,
data: any[]
):Promise<any>{
if (!data || data.length === 0) {
return Promise.resolve();
}
return Promise.all(
data.map((data)=> {
return this.selectByKey(storeName,data.docId)
.then((res)=> {
if(res&&res.docId) {
data.viewed = "1";
}
return Promise.resolve();
})
})
)
.catch((error) => {
console.error(error);
return Promise.reject(error);
});
}
// 清除30天前的數據
cleanViewDB(){
this.open().then(()=>{
// 通過IDBDatabase得到IDBTransaction
let transaction = this.db.transaction('viewedDoc', 'readonly');
// 通過IDBTransaction得到IDBObjectStore
let objectStore = transaction.objectStore("viewedDoc");
// 打開遊標,遍歷customers中所有數據
objectStore.openCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
let key = cursor.key;
let rowData = cursor.value;
var time1 = new Date(rowData.lastViewTime);
var time2 = new Date();
if(Math.abs(time2.getTime() - time1.getTime())>2592000000){// 清除三十天前的數據
this.workdelete('viewedDoc',cursor.key);
}
cursor.continue();
}
}.bind(this);
})
}
}