IndexedDB使用(基本函數封到Angular2的service裏)

IndexedDB使用

使用場景

  • 具體使用場景:

存儲用戶瀏覽記錄。

  • 適合的使用場景:

    1. 處於安全性考慮,數據不能存儲到服務器端。
    2. 數據爲結構性數據或者數據量較大,不適合使用cookies。
    3. 希望數據不隨着客戶清理緩存而刪除。此時我們一定一定要設計好清理瀏覽器端數據的時機。

相關站點

  1. MDN文檔(中英) 訪問
  2. IBM develoerWorks(中文) 訪問
  3. 這個可能是最權威的了吧,W3C(英文)訪問

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);
    })
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章