簡體   English   中英

Javascript 代碼在使用存儲服務的 Firefox 擴展中太慢

[英]Javascript code too slow in Firefox extension using Storage service

我在 firefox 擴展中運行以下 javascript 代碼

highlightLinks: function(e) {

  var anchors = e.target.getElementsByTagName("a");
  let file = Components.classes["@mozilla.org/file/directory_service;1"]
                  .getService(Components.interfaces.nsIProperties)
                  .get("ProfD", Components.interfaces.nsIFile);
  file.append("test.sqlite");

  var storageService = Components.classes["@mozilla.org/storage/service;1"]
          .getService(Components.interfaces.mozIStorageService);
  var conn = storageService.openDatabase(file);

  for (var i = 0; i < anchors.length; i++) {
    var statement = conn.createStatement("select * from links where url=?1");
    statement.bindStringParameter(0, anchors[i].href);
    var visited = false;
    try {
      while (statement.executeStep()) {
        visited = true;
        break;
      }
    } catch (e) {
    } finally {
      statement.reset();
    }
    statement.finalize();
    if (visited) {
      anchors[i].innerHTML += "+";
    }
  }
  conn.close();
},

這個 function 在 DOMContentLoaded 事件上運行。 它檢查頁面上的每個鏈接是否存在於test.sqlite數據庫中並標記存在的鏈接。

問題是現在頁面的加載速度要慢得多(尤其是當我降低 CPU 頻率時)。 你能幫我提高這段代碼的效率和節省資源嗎?

編輯:通過刪除 function 和的事件偵聽器,實現了顯着的加速。

謝謝你

如果您將createStatement拉出循環並重用它,每次都重新綁定參數,它會更快。 存儲文檔說:“注意:如果您需要多次執行一條語句,緩存 createStatement 的結果會給您帶來顯着的性能提升,因為 SQL 查詢不需要每次都解析。”

所以而不是:

for (var i = 0; i < anchors.length; i++) {
  var statement = conn.createStatement("select * from links where url=?1");
  statement.bindStringParameter(0, anchors[i].href);
  // ... do stuff with results

寫:

var statement = conn.createStatement("select * from links where url=?1");
for (var i = 0; i < anchors.length; i++) {
  statement.bindStringParameter(0, anchors[i].href);
  // ... do stuff with results

編輯:另外,如果您使用的是最近的 Firefox,您可以使用他們的異步 API 以避免延遲 UI。 不要調用executeStep ,而是使用executeAsync

statement.executeAsync({
  handleResult: function(aResultSet) {
    // ... do stuff with results
  },

  handleError: function(aError) {
    print("Error: " + aError.message);
  },

  handleCompletion: function(aReason) {
    if (aReason != Components.interfaces.mozIStorageStatementCallback.REASON_FINISHED)
      print("Query canceled or aborted!");
  }
});

第一個提示,雖然不會節省太多時間,但在 for 循環的條件下不使用 anchors.length。 更好的使用:

for(var i = 0, num = anchors.length; i < num, i++) {...}

通常,當您調用數據庫(而不是瀏覽器的數據庫)時,最好進行一次調用,將所需的所有數據獲取到數組或 hash 中,然后在內部使用它們。

編輯:

我會這樣做:從存儲中加載所有鏈接並構建 hash ,例如:

linksHash = {
  'url-1':true,
   ...,
  'url-n':true
}

然后循環anchors並使用以下內容進行檢查:

if(linksHash[anchors[i].href]){
 //the link href is in the hash
}

然后,如果您注意到 RAM 成為問題,請將表的負載分成 2 塊或更多塊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM