useEffect钩子内while循环无法运行,如何实现每7秒获取设备定位?
存在的问题
- 自定义的
sleep函数无效:setTimeout是异步API,调用后会立刻返回不会阻塞主线程,你的sleep函数没有任何等待效果,导致while(true)会瞬间无限循环调用GetLocation.getCurrentPosition,直接占满JS主线程资源,后续的定位回调、UI渲染全部被阻塞,看起来就像循环没有执行。 - 单线程阻塞问题:JS是单线程执行模型,同步的死循环会一直占用执行栈,所有异步任务(包括定位的then回调、setTimeout回调)都只能在任务队列等待,永远得不到执行机会。
- 缺少清理逻辑:没有处理组件卸载时的定时任务终止逻辑,会导致内存泄漏、组件卸载后依然继续请求定位的问题。
正确实现方案
采用递归setTimeout实现间隔请求,既能保证两次请求的间隔为7秒,也能避免定位请求超时导致的任务堆叠问题,同时增加卸载清理逻辑:
useEffect(() => { let timerId = null; let isUnmounted = false; // 标记组件是否卸载,避免卸载后更新state报错 const getPosition = async () => { try { const location = await GetLocation.getCurrentPosition({ enableHighAccuracy: true, timeout: 15000, }); if (!isUnmounted) { const { latitude, longitude, altitude, accuracy } = location; setPosition({ lat: latitude, lon: longitude, alt: altitude, acc: accuracy }); setLoading(false); } } catch (err) { if (!isUnmounted) alert(err); } finally { // 无论请求成功失败,都等待7秒后发起下一次请求 if (!isUnmounted) { timerId = setTimeout(getPosition, 7000); } } }; // 发起第一次定位请求 getPosition(); // 组件卸载时清理定时任务 return () => { isUnmounted = true; clearTimeout(timerId); }; }, []);
内容的提问来源于stack exchange,提问作者cagri
相关产品推荐
相关产品推荐

