Javascript 用jQuery异步遍历DOM树
我希望对DOM执行一次长时间运行的逐节点遍历,在每个节点上调用一个函数,但不会使浏览器无响应。 所以我认为异步是一种方式 我认为jQuery延迟对象可以提供一个解决方案,但我还没有想出一个解决方案 有谁能举例说明如何使用jQuery(或者其他库,如果其中一个特别适合的话;或者纯Javascript和DOM方法)做到这一点Javascript 用jQuery异步遍历DOM树,javascript,jquery,dom,asynchronous,tree-traversal,Javascript,Jquery,Dom,Asynchronous,Tree Traversal,我希望对DOM执行一次长时间运行的逐节点遍历,在每个节点上调用一个函数,但不会使浏览器无响应。 所以我认为异步是一种方式 我认为jQuery延迟对象可以提供一个解决方案,但我还没有想出一个解决方案 有谁能举例说明如何使用jQuery(或者其他库,如果其中一个特别适合的话;或者纯Javascript和DOM方法)做到这一点 更复杂的是,我希望能够以不同的顺序进行遍历,例如postorder,但这还不是必需的。如果可以使用HTML5,一些浏览器支持web工作人员。 这可能是一种选择。您可以将DOM作
更复杂的是,我希望能够以不同的顺序进行遍历,例如postorder,但这还不是必需的。如果可以使用HTML5,一些浏览器支持web工作人员。
这可能是一种选择。您可以将DOM作为文档传递给方法并从那里开始。如果您可以使用HTML5,某些浏览器支持web工作者。
这可能是一种选择。您可以将DOM作为文档传递给方法并从那里开始。您可以使用setTimeout递归地执行此操作。因为Javascript是单线程的,所以可以通过周期性地放弃线程来创建拥有多个线程的假象。调用setTimeout将对剩余的工作进行排队,并在继续之前处理任何未完成的事件 下面是一个使用jQuery的工作示例:
function traverse(node, visitor, root) {
if (root === undefined)
root = node;
visitor(node, function() {
if (!node.length)
return;
let nextNode;
if (node.children().length) {
nextNode = node.children().first();
} else {
nextNode = node;
do {
if (root.length && nextNode.length && nextNode[0] == root[0]) {
nextNode = $();
break;
} else if (nextNode.next().length) {
nextNode = nextNode.next();
break;
} else {
nextNode = nextNode.parent();
}
} while (nextNode.length);
}
setTimeout(function() { traverse(nextNode, visitor, root); }, 200);
});
}
这将使用所有DOM节点调用visitor
,然后使用空jQuery对象调用visitor
,以指示已完成<代码>访问者必须调用其第二个参数才能继续遍历:
traverse($('#rootNode'), function(node, proceed) {
if (!node.length) {
console.log('done with traversal');
// no proceed() call at the end
} else if (node.hasClass('my-class')) {
// let's say that this click triggers an AJAX request that makes a node visible later in traversal
node.trigger('click');
proceed(); // continue traversal
} else if (node.hasClass('ajax-response-container')) {
function checkIfVisible() {
if (node.is(':visible')) {
// yay, ajax response arrived
console.log('AJAX response', node.html());
// continue traversal
proceed();
} else {
// wait for ajax node to become visible
window.requestAnimationFrame(checkIfVisible);
// no proceed() call - don't continue traversal yet
}
}
checkIfVisible();
} else {
// continue traversal for any other node encountered
proceed();
}
});
您可以使用setTimeout递归地执行此操作。因为Javascript是单线程的,所以可以通过周期性地放弃线程来创建拥有多个线程的假象。调用setTimeout将对剩余的工作进行排队,并在继续之前处理任何未完成的事件 下面是一个使用jQuery的工作示例:
function traverse(node, visitor, root) {
if (root === undefined)
root = node;
visitor(node, function() {
if (!node.length)
return;
let nextNode;
if (node.children().length) {
nextNode = node.children().first();
} else {
nextNode = node;
do {
if (root.length && nextNode.length && nextNode[0] == root[0]) {
nextNode = $();
break;
} else if (nextNode.next().length) {
nextNode = nextNode.next();
break;
} else {
nextNode = nextNode.parent();
}
} while (nextNode.length);
}
setTimeout(function() { traverse(nextNode, visitor, root); }, 200);
});
}
这将使用所有DOM节点调用visitor
,然后使用空jQuery对象调用visitor
,以指示已完成<代码>访问者必须调用其第二个参数才能继续遍历:
traverse($('#rootNode'), function(node, proceed) {
if (!node.length) {
console.log('done with traversal');
// no proceed() call at the end
} else if (node.hasClass('my-class')) {
// let's say that this click triggers an AJAX request that makes a node visible later in traversal
node.trigger('click');
proceed(); // continue traversal
} else if (node.hasClass('ajax-response-container')) {
function checkIfVisible() {
if (node.is(':visible')) {
// yay, ajax response arrived
console.log('AJAX response', node.html());
// continue traversal
proceed();
} else {
// wait for ajax node to become visible
window.requestAnimationFrame(checkIfVisible);
// no proceed() call - don't continue traversal yet
}
}
checkIfVisible();
} else {
// continue traversal for any other node encountered
proceed();
}
});
您可以查看dom中的异步操作到底是哪种操作。您可以查看dom中的异步操作到底是哪种操作。您可能需要检查这种方法
基于Kris Kowal的Q库。基本上与SynXsiS的想法相似,但在承诺/差异对象方面有点结构化。您可能需要检查这种方法
基于Kris Kowal的Q库。基本上与SynXsiS的想法相似,但在承诺/不同对象方面更具结构化。google“multithread javascript”您可以在那里找到库和答案(今天我自己也搜索了相同的内容…),您有什么想法?老实说,我只是好奇。谷歌“多线程javascript”你可以在那里找到库和答案(今天我自己也搜索了相同的东西…)你有什么想法?老实说,我只是好奇。Web工作人员无法访问DOM,因此他们不会帮助进行“长时间运行的DOM逐节点漫游”。Web工作人员无法访问DOM,因此他们不会帮助进行“长时间运行的DOM逐节点漫游”。while(parent&&!parent.next())是否存在
问题
因为父对象是jQuery对象,所以它总是非空的。另外,它是否需要停止向上到达传入节点上方的父节点?@jfriend00您是对的。您可能希望检查父级的长度。关于检查父节点是否为起始节点,也请更正。该代码更像是psuedo代码,用于启动OP。while(parent&&!parent.next())是否存在问题,因为parent是jQuery对象,所以它总是非空的。另外,它是否需要停止向上到达传入节点上方的父节点?@jfriend00您是对的。您可能希望检查父级的长度。关于检查父节点是否为起始节点,也请更正。这段代码更像是psuedo代码,用于启动操作。