ajax responseText验证函数冻结页面内容(异步)

时间:2012-07-16 18:23:16

标签: javascript ajax responsetext ajax-request

我写了一个很大的功能来使用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();
};

1 个答案:

答案 0 :(得分:1)

好的,首先问题是你有这个巨大的功能不断抓取所有元素,然后在每个迭代级别重新抓取相同的节点。

至少你没有将div添加到DOM中,然后再这样做 - 这将是JS自杀。

为什么不进行深度优先遍历,使用递归,这至少可以节省抓取所有子元素的时间,多次(除非你确定要拆除你的堆栈,在这种情况下,几乎没有你可以做到一个快速的功能)?

另外:JS是单线程的。如果你一次性地咀嚼所有这些,你的UI将完全没有反应,直到你完成所有这些。

走向递归路线,如果你将这个功能分解为多个步骤,也可以让你恢复你的用户界面。

如果你可以添加一个简单的10ms setTimeout(recurseHTML,10);在那里(或一个包含你想要发送的任何参数的匿名函数),这将使浏览器有时间完成用户一直等待执行的任何交互。

这意味着你必须更加努力地思考如何满足你的“完成”条件,这意味着你必须等待一段时间才能完成整个过程 - 但是可用性胜过两者那些东西。