我写了一个很大的功能来使用Ajax Request
在我的网站上更新内容,但是使用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 :(得分:1)
好的,首先问题是你有这个巨大的功能不断抓取所有元素,然后在每个迭代级别重新抓取相同的节点。
至少你没有将div添加到DOM中,然后再这样做 - 这将是JS自杀。
为什么不进行深度优先遍历,使用递归,这至少可以节省抓取所有子元素的时间,多次(除非你确定要拆除你的堆栈,在这种情况下,几乎没有你可以做到一个快速的功能)?
另外:JS是单线程的。如果你一次性地咀嚼所有这些,你的UI将完全没有反应,直到你完成所有这些。
走向递归路线,如果你将这个功能分解为多个步骤,也可以让你恢复你的用户界面。
如果你可以添加一个简单的10ms setTimeout(recurseHTML,10);在那里(或一个包含你想要发送的任何参数的匿名函数),这将使浏览器有时间完成用户一直等待执行的任何交互。
这意味着你必须更加努力地思考如何满足你的“完成”条件,这意味着你必须等待一段时间才能完成整个过程 - 但是可用性胜过两者那些东西。