2012-07-16 61 views
0

我寫了一個很大的函數來更新我的網站上的內容使用Ajax Request,但與responseText一起使用的函數凍結了我的頁面。ajax responseText驗證功能凍結頁面內容(異步)

有人可以給我一個提示,爲什麼發生這種情況?

這裏是我的功能:

//process Ajax responseText 
window.processResponse = function(response) { 
    if (!response) return; 
    var div = document.createElement("div"); 
    div.innerHTML = response; 
    var divElements = div.getElementsByTagName("*"); 
    var divChildren = div.children; 
    //set unique id for each element and save all ids in array 
    var ids = []; 
    for (var i = 0; i < divElements.length; i++) { 
     var em = divElements[i]; 
     if (!em.id) { 
      var hash = (em.innerHTML || em.outerHTML).toHash(); 
      var o = 0; 
      if (ids.inArray(hash)) em.id = hash + "_" + (++o); 
      else em.id = hash; 
     } 
     ids.push(em.id); 
    } //endfor 
    for (var i = 0; i < divChildren.length; i++) { 
     var root = divChildren[i]; 
     var documentRoot = document.getElementById(root.id); 
     if (documentRoot) { 
      if (documentRoot.getAttribute("page") != root.getAttribute("page")) { 
       documentRoot.innerHTML = root.innerHTML; 
       documentRoot.setAttribute("page", root.getAttribute("page")); 
       return; 
      } 
      var pageHash = div.innerHTML.toHash(); 
      if (documentRoot.getAttribute("hash") == pageHash) { 
       return; 
      } 
      documentRoot.setAttribute("hash", pageHash); 
      var rootElements = root.getElementsByTagName("*"); 
      var node = null; 
      var prevNode = {}; 
      var parentNode = null; 
      var documentNode = null; 
      var documentParentNode = null; 
      var index = 0; 
      var noChange = {}; 
      while (node = rootElements[index++]) { 
       parentNode = node.parentNode; 
       if (noChange[parentNode.id]) { 
        continue; 
       } 
       documentNode = document.getElementById(node.id); 
       documentParentNode = document.getElementById(parentNode.id); 
       if (!documentNode) { 
        //if element not exists then create new node 
        if (prevNode[parentNode.id]) documentParentNode.insertBefore(node, prevNode[parentNode.id].nextSibling); 
        else documentParentNode.insertBefore(node, documentParentNode.firstChild); 
        documentNode = node; 
        index--; 
       } else { 
        //if node exists then check it's content 
        if (!node.children[0] && !documentNode.children[0]) { 
         var nodeHash = (node.innerHTML || node.outerHTML).toHash(); 
         var documentHash = (documentNode.innerHTML || documentNode.outerHTML).toHash(); 
         if (nodeHash != documentHash) { 
          documentNode.parentNode.insertBefore(node, documentNode.nextSibling); 
          documentNode.parentNode.removeChild(documentNode); 
          documentNode = node; 
          index--; 
         } 
        } 
        //if loaded node has no children then just replace old node with new one 
        else if (!node.children[0]) { 
         documentNode.parentNode.insertBefore(node, documentNode.nextSibling); 
         documentNode.parentNode.removeChild(documentNode); 
         documentNode = node; 
         index--; 
        } else { 
         var nodeHash = (node.innerHTML || node.outerHTML).toHash(); 
         var documentHash = (documentNode.innerHTML || documentNode.outerHTML).toHash(); 
         if (nodeHash == documentHash) noChange[node.id] = true; 
        } 
       } 
       //save previous node 
       prevNode[parentNode.id] = documentNode; 
      } //endwhile 
      //remove unneded nodes 
      var documentRootElements = documentRoot.getElementsByTagName("*"); 
      for (var j = 0; j < documentRootElements.length; j++) { 
       if (!ids.inArray(documentRootElements[j].id)) { 
        documentRootElements[j].parentNode.removeChild(documentRootElements[j]); 
        j--; 
       } 
      } //endfor 
     } 
    } //endfor 
}; 
//generate hashCode from string 
String.prototype.toHash = function() { 
    var hash = 0, 
     i, chr; 
    var str = this.clear(); 
    if (str.length == 0) return hash; 
    for (i = 0; i < str.length; i++) { 
     chr = str.charCodeAt(i); 
     hash = ((hash << 5) - hash) + chr; 
     hash = hash & hash; 
    } 
    return hash.toString(); 
}; 
+0

具有多個DOM讀寫的循環和循環。大數據集的速度會很慢。 – epascarello 2012-07-16 18:29:00

+0

@epascarello在我看來,這是「精選內容更新」的唯一選擇。通過「選擇性更新」,我的意思是:僅在需要的時間和時間添加新內容並跳過相同的內容。 – John 2012-07-16 18:34:12

+0

爲什麼它會帶回已有的內容?知道改變了什麼不是很聰明嗎? – epascarello 2012-07-16 18:42:59

回答

1

好了,第一個問題是,你有這個巨大的功能是不斷搶佔了所有的元素,然後重新抓住了相同的節點在迭代的每個級別。

至少你不會將div附加到DOM,在這之前 - 這將是JS自殺。

爲什麼不進行深度優先遍歷,使用遞歸,這將至少節省抓取所有子元素的時間,多次(除非您確定要拆除堆棧,在這種情況下,有你可以做一些快速的功能)?

另外:JS是單線程的。如果你一口氣咀嚼所有這些,你的用戶界面將會完全沒有響應,直到你完成整個過程。

進入遞歸路線,如果你把這個功能分成多個步驟,也可以讓你回到你的用戶界面。

如果你可以添加一個簡單的10ms setTimeout(recurseHTML,10);在那裏(或者一個匿名函數,它包含你想要發送的任何參數),這將使瀏覽器有時間完成用戶等待執行的任何交互。

這意味着您必須更加努力地思考如何滿足您的「完成」條件,這意味着您需要等待一段時間才能完成流程 - 但可用性勝過兩者那些東西。