软件教程 2025年08月6日
0 收藏 0 点赞 304 浏览 2985 个字
摘要 :

文章目录 一、新手常踩的雷:同步递归 二、比同步递归还“坑”的while循环 三、setTimeout递归:安全但有点“慢半拍” 四、事件驱动:MutationObserver监听变化 五、Promise……




  • 一、新手常踩的雷:同步递归
  • 二、比同步递归还“坑”的while循环
  • 三、setTimeout递归:安全但有点“慢半拍”
  • 四、事件驱动:MutationObserver监听变化
  • 五、Promise + 轮询:强烈推荐的最优解
  • 六、性能对比
  • 七、总结

前端开发这行摸爬滚打,大家肯定都遇到过数据还没准备好就得用的糟心事。就拿微前端架构来说,咱们常常得等 props.parentRoute 这个值变成有效的,才能接着执行渲染逻辑。有些小伙伴一着急,就直接用递归等这个值,可这要是没考虑周全,那麻烦可就大了,页面卡死、性能拉胯,甚至还可能内存泄漏,项目直接“凉凉”。今天咱就好好唠唠怎么在获取这个数据的时候,巧妙地避开递归的那些坑,找到优雅获取数据的方法。

一、新手常踩的雷:同步递归

先来说说不少初学者容易犯的错——同步递归。看下面这段代码:

function waitForParentRoute(props) {
  if (props.parentRoute) {
    console.log(\'parentRoute 获取成功\', props.parentRoute);
    return;
  }
  return waitForParentRoute(props);  // 直接递归调用
}

要是 props.parentRoute 一直是 undefined ,这代码可就“失控”了。它会不停地递归调用自己,就像一个停不下来的陀螺,最后导致栈溢出,报“Maximum call stack size exceeded”错误。这时候,页面直接就卡死了,浏览器也跟着崩溃,用户体验直接“归零”。所以啊,这种同步递归的方式在处理异步数据获取的时候,就像一颗“定时炸弹”,千万不能这么用!

二、比同步递归还“坑”的while循环

有些小伙伴可能会想,用 while 循环来等这个值是不是行得通呢?来看看这段代码:

function waitForParentRoute(props) {
  while (!props.parentRoute) {
    // 等待 parentRoute 变为可用
  }
  console.log(\'parentRoute 获取成功\', props.parentRoute);
}

想法是挺美好的,但现实很残酷。while 循环是同步阻塞的,它一旦开始执行,就会疯狂占用CPU资源,把浏览器忙得不可开交,根本没精力去响应其他任务。结果就是页面直接卡死,用户啥操作都做不了,这比同步递归还糟糕,大家可千万别这么干!

三、setTimeout递归:安全但有点“慢半拍”

上面两种方法都不靠谱,那用 setTimeout 递归呢?看看下面的代码:

function waitForParentRoute(props) {
  if (props.parentRoute) {
    console.log(\'parentRoute 获取成功\', props.parentRoute);
    return;
  }
  setTimeout(() => waitForParentRoute(props), 50);
}

这种方式有它的优点,因为 setTimeout 是异步的,不会卡死主线程,浏览器还能正常响应用户的其他操作,不会让用户感觉整个页面“死机”了。不过呢,它也有缺点,就是会有一定的延迟,这个延迟时间取决于 setTimeout 设置的时间间隔。而且,它可能得执行好几次才能获取到数据,效率比起后面要说的事件监听方式要低一些。虽说它在大部分场景下能用,但还是有优化的空间。

四、事件驱动:MutationObserver监听变化

要是 props.parentRoute 是绑定在某个DOM或者对象上的,咱们可以用 MutationObserver 来监听它的变化,代码长这样:

function waitForParentRoute(props, callback) {
  if (props.parentRoute) {
    callback(props.parentRoute);
    return;
  }

  const observer = new MutationObserver(() => {
    if (props.parentRoute) {
      callback(props.parentRoute);
      observer.disconnect();  // 监听到值后立即停止监听,防止性能浪费
    }
  });

  observer.observe(document, { subtree: true, childList: true });
}

这种方式的优势很明显,它非常高效,几乎没有延迟,只要 parentRoute 的值一变化,就能马上触发相应的逻辑。而且它不怎么占用CPU资源,只有在值变化的时候才会执行相关操作。不过,它也有个限制,就是只能监听DOM的变化。要是 props.parentRoute 不是和DOM相关的属性,那这个方法就用不了了。所以,它比较适合 parentRoute 和DOM绑定的情况。

五、Promise + 轮询:强烈推荐的最优解

如果 props.parentRoute 就是个普通变量,那用 Promise 结合 setTimeout 进行非阻塞轮询,就是目前最推荐的方法啦!代码如下:

function waitForParentRoute(props, interval = 50, timeout = 5000) {
  return new Promise((resolve, reject) => {
    const start = Date.now();

    const check = () => {
      if (props.parentRoute) {
        resolve(props.parentRoute);
      } else if (Date.now() - start > timeout) {
        reject(new Error(\'等待超时\'));
      } else {
        setTimeout(check, interval);
      }
    };

    check();
  });
}

这个方法的好处可不少。首先,它不会阻塞UI,setTimeout 让轮询在后台默默进行,用户操作页面完全不受影响。其次,它还支持超时机制,就算数据一直没准备好,也不会一直等下去,避免了死循环的情况。而且代码逻辑清晰,后续维护起来也轻松。当然,它也不是十全十美,还是会有一点点延迟,这个延迟取决于设置的轮询时间 interval 。但总体来说,它是最通用的解决方案,强烈推荐给大家!

六、性能对比

为了让大家更直观地看出这些方法的差异,咱们来做个性能对比:

方案 是否阻塞UI 是否高效 是否安全 适用场景
同步递归 🚨阻塞 ❌效率极低 ❌栈溢出风险 不推荐
while循环 🚨阻塞 ❌CPU占满 ❌页面卡死 禁用
setTimeout递归 ✅非阻塞 ⏳可能有延迟 ✅安全 适用于大部分场景
MutationObserver ✅非阻塞 ✅高效 ✅适用于DOM变化 适用于监听DOM
Promise轮询 ✅非阻塞 ✅高效 ✅安全 最推荐

七、总结

总结一下,同步递归和 while 循环这两种方式在处理异步等待 props.parentRoute 数据的时候,简直就是“大坑”,千万不能用,不然页面卡死没商量。setTimeout 递归虽然能用,但有延迟这个小瑕疵。MutationObserver 适合监听DOM变化的场景。而 Promise 轮询则是综合来看最推荐的通用方案,既不会阻塞UI,又有超时控制,用起来相当靠谱。

大家在自己的项目里是怎么处理类似的异步等待问题的呢?有没有更巧妙的方法?欢迎在评论区分享,咱们一起交流进步!

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/6848.html

管理员

相关推荐
2025-08-06

文章目录 一、Promise基础回顾 二、Promise 与 axios 结合使用场景及方法 (一)直接返回 axios …

269
2025-08-06

文章目录 一、模块初始化时的内部机制 二、常见导出写法的差异分析 (一)写法一:module.exports…

107
2025-08-06

文章目录 一、ResizeObserver详解 (一)ResizeObserver是什么 (二)ResizeObserver的基本用法 …

683
2025-08-06

文章目录 一、前期准备工作 (一)下载相关文件 (二)安装必要工具 二、处理扣子空间生成的文件…

338
2025-08-06

文章目录 一、官方文档 二、自动解包的数据类型 ref对象:无需.value即可访问 reactive对象:保持…

371
2025-08-06

文章目录 一、Hooks的工作原理 二、在if语句中使用Hook会出什么岔子? 三、React官方的Hook使用规…

843
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号