嵌套匿名函数调用中find()未更新致无限循环及优化咨询
问题分析与解决方案
问题根源
你这段代码的死循环是因为jQuery的find()方法永远返回一个jQuery对象,哪怕没找到匹配元素,这个对象在布尔判断里也是true,所以if ($(el).find('.updating'))永远成立,永远不会走到else分支,导致无限递归调用。
修复与优化方案
方案1:修复判断逻辑,保留递归写法
把判断改成检查匹配元素的数量,确保只有真的找到.updating时才重试:
this.TryClick = function (el) { // 用length判断是否存在目标元素 if ($(el).find('.updating').length) { setTimeout(() => { self.TryClick(el); }, 1000); } else { const btn = $(el).find('.myclass'); btn.click(); } };
方案2:用setInterval替代递归(更简洁)
用定时轮询替代递归,找到.updating消失后立即清理定时器并执行点击,避免嵌套调用:
this.TryClick = function (el) { const timer = setInterval(() => { if (!$(el).find('.updating').length) { clearInterval(timer); $(el).find('.myclass').click(); } }, 1000); };
方案3:用MutationObserver监听(性能最优)
如果不想定时轮询,可以用浏览器原生的MutationObserver监听元素类变化,.updating一被移除就触发点击,完全不用等待间隔:
this.TryClick = function (el) { const domEl = $(el)[0]; const hasUpdating = $(el).find('.updating').length > 0; if (!hasUpdating) { $(el).find('.myclass').click(); return; } const observer = new MutationObserver(() => { if (!$(el).find('.updating').length) { observer.disconnect(); $(el).find('.myclass').click(); } }); // 监听元素及其子元素的类属性变化 observer.observe(domEl, { subtree: true, attributes: true, attributeFilter: ['class'] }); };
方案选择
- 递归写法:逻辑简单,适合小场景,不会有栈溢出问题(因为setTimeout是异步的)
- setInterval:代码更清爽,避免嵌套,日常用足够
- MutationObserver:性能最好,没有轮询的等待延迟,适合对响应速度要求高的场景
内容的提问来源于stack exchange,提问作者Jason Bee
相关产品推荐
相关产品推荐

