2016-01-10 32 views
3

你好我正在建立一個應用程序,我在其中使用indexeDB。基於應用程序配置,我可以選擇是否應該從WebWorker或主UI線程使用indexeDB。無論配置如何,主UI線程的連接總是在進行。但是,根據配置,如果選擇了繁重的工作,那麼工人將完成繁重的工作。進口樣機的IndexedDB主線程和WebWorker eventlisteners

例子:

Database.prototype.importItem = function(item, callback) { 

    if (this.settings.useWorker) { 

     this.postMessage({ 
      cmd: "importItem", 
      data: item 
     }, callback); 

    } else { 

     var that = this; 
     var transaction = this.db.transaction(this.settings.collection, "readwrite"); 
     var objectStore = transaction.objectStore(this.settings.collection); 
     var request = objectStore.add(item); 

     request.onerror = function(evt) { 
      if (callback && callback instanceof Function) { 
       callback(new ApplicationError("importItem error", evt.target.error), null); 
      } 
     }; 

     request.onsuccess = function(evt) { 
      if (callback && callback instanceof Function) { 
       callback(null, evt.target.result); 
      } 
     }; 

     transaction.oncomplete = function(evt) {}; 

    } 
}; 

我很好奇的想法是,從索引資料所需的事件監聽器,例如:

Database.prototype.connect = function() { 

    if (!this.supported()) { 
     return this.emit("error", new ApplicationError("IndexedDB not supported!")); 
    } 

    var that = this; 
    var openRequest = window.indexedDB.open(this.settings.dbName, this.settings.dbVersion); 

    /** 
    * [onerror description] 
    * @param {[type]} evt [description] 
    * @return {[type]}  [description] 
    */ 
    openRequest.onerror = function(evt) { 
     that.emit("error", new ApplicationError("openRequest.onerror error", evt.target.error)); 
    }; 

    /** 
    * [onblocked description] 
    * @param {[type]} evt [description] 
    * @return {[type]}  [description] 
    */ 
    openRequest.onblocked = function(evt) { 
     // If some other tab is loaded with the database, then it needs to be closed 
     // before we can proceed. 
     alert("Please close all other tabs with this site open!"); 
    }; 

    /** 
    * [onsuccess description] 
    * @param {[type]} evt [description] 
    * @return {[type]}  [description] 
    */ 
    openRequest.onsuccess = function(evt) { 

     that.db = evt.target.result; 

     that.db.onerror = function(evt) { 
      logger.warn("openRequest.onsuccess error", evt.target); 
     }; 

     that.db.onabort = function(evt) { 
      logger.warn("openRequest.onsuccess abort", evt.target); 
     }; 

     that.db.onversionchange = function(evt) { 
      that.db.close(); 
      that.emit("versionchange", new ApplicationError("openRequest.onsuccess version change", evt.target)); 
     }; 

     if (that.settings.useWorker) { 
      that.requestWorker(); 
     } else { 
      that.emit("connect"); 
     } 

    }; 

    /** 
    * [onupgradeneeded description] 
    * @param {[type]} evt [description] 
    * @return {[type]}  [description] 
    */ 
    openRequest.onupgradeneeded = function(evt) { 

     var stores = {}; 

     that.db = evt.target.result; 

     that.db.onerror = function(evt) { 
      logger.warn("openRequest.onupgradeneeded error", evt.target); 
     }; 

     that.db.onabort = function(evt) { 
      logger.warn("openRequest.onupgradeneeded abort", evt.target); 
     }; 

     that.db.onversionchange = function(evt) { 
      that.db.close(); 
      that.emit("versionchange", new ApplicationError("openRequest.onupgradeneeded version change", evt.target)); 
     }; 

     // Check for the objectStore - collection and delete it if exists 
     if (that.db.objectStoreNames.contains(that.settings.collection)) { 
      that.db.deleteObjectStore(that.settings.collection); 
     } 

     // Create new objectStore 
     stores[that.settings.collection] = that.db.createObjectStore(that.settings.collection, { 
      keyPath: that.settings.indexes[0] 
     }); 

     // Create database indexes 
     that.settings.indexes.forEach(function(index) { 
      stores[that.settings.collection].createIndex(index, index, { 
       unique: false 
      }); 
     }); 

     that.upgraded = true; 
     that.emit("upgrade"); 

    }; 

    /** 
    * [onbeforeunload description] 
    * @param {[type]} evt [description] 
    * @return {[type]}  [description] 
    */ 
    window.onbeforeunload = function(evt) { 
     that.db.close(); 
    }; 

}; 

由於我第一次從連接總是主要的用戶界面,然後從工作人員,我應該只在主UI線程而不是工作人員監聽像「onblocked,versionchange」這樣的事件嗎?我假設不需要從兩個線程中聽取?

UPDATE

我知道,這是一個奇怪的實現,但我想它的原因是因爲我建立一個非常機到有RAM的3GB和2個核心上的應用...此外,我有一個方法,從我的數據庫迭代集合中的所有記錄。我在想的是將每條記錄都傳回到另一個方法來處理圖像,然後可能調用回調......這會限制內存使用,因爲如果我沒有弄錯,它會在系列中完成。但是我不確定交易是否仍然活着。

底線是我考慮進行2連接的主要原因(因爲有1個方法),而且我想知道是否可以避免雙重事件監聽器。也許有一些線程在其中。

+0

爲什麼你甚至連接兩個線程,如果你總是隻使用一個線程的indexedDB? –

+0

由於webworker不支持某些方法。例如,我有一個迭代集合中所有項目的方法,並將光標傳遞給執行畫布繪製的回調,並且Web工作人員不支持畫布。 – Syd

+0

是的,但是您不需要主線程中的indexedDB連接 - 您仍然可以檢索Worker中的數據並將它們發送到主線程;然後畫在畫布上。您不需要從主線程和工作者連接。你所描述的只是糟糕的設計,或者你描述的錯誤。 –

回答

1

你做錯了。兩個線程都不應該打開IndexedDB連接。它使您的應用程序架構不必要地複雜化。從IndexedDB檢索的數據可以通過Web workers' messaging channel與UI線程輕鬆交換。

+0

是的你是正確的我改變了我的實施。然而關於封鎖等事件只在活動線程(worker或main)中被監控,並且消息正在發送給用戶 – Syd

+0

@Syd我不明白你的觀點。你能澄清一下嗎?爲什麼*封鎖等事件只在活動線程中受到監控*是一件大事? – Lewis

+1

事件在特定的對象實例(例如請求,事務,連接)被觸發,它們只存在於工作者或窗口上下文中,並且不能被傳送。因此,如果您在工作人員中打開連接,則無法偵聽來自窗口的事件,因爲您沒有任何事件可以附加到事件偵聽器。 –