如何检测Hotjar在JS中已加载并解决获取userId报错问题?
嘿,我来帮你搞定这个问题!你碰到的TypeError本质上是代码跑早了——Hotjar的hj对象还没加载初始化完成,自然就找不到hj.globals啦。下面给你详细的解决方案:
如何判断Hotjar是否加载完成
Hotjar加载就绪的核心标志是全局hj对象存在,且hj.globals属性可用。因为Hotjar脚本是异步加载的,直接同步执行依赖hj的代码大概率会出错,我们需要用异步等待的方式确保它准备好。
用Promise等待Hotjar加载并获取userId
这里提供两种实用方案,你可以根据自己的场景选择:
方案1:轮询等待hj就绪(最通用)
这种方式不需要依赖Hotjar的特定回调,兼容性最好:
// 封装一个Promise,等待Hotjar完全就绪 function waitForHotjar() { return new Promise((resolve) => { // 如果hj已经加载好,直接返回 if (window.hj && hj.globals) { resolve(hj); return; } // 每100ms检查一次,直到hj可用 const checkInterval = setInterval(() => { if (window.hj && hj.globals) { clearInterval(checkInterval); resolve(hj); } }, 100); }); } // 使用示例 waitForHotjar().then((hj) => { try { // 安全获取并处理userId const userId = hj.globals.get('userId').split('-').shift(); console.log('Hotjar用户ID:', userId); // 这里写你需要用userId做的逻辑 } catch (err) { console.error('获取Hotjar用户ID失败:', err); } });
方案2:监听Hotjar脚本的加载事件(更精准)
如果你能定位到页面中的Hotjar脚本标签,可以直接监听它的加载完成事件:
function waitForHotjarScript() { return new Promise((resolve, reject) => { const hotjarScript = document.querySelector('script[src*="hotjar.com"]'); if (!hotjarScript) { reject(new Error('页面中未找到Hotjar脚本')); return; } // 脚本已加载完成的情况 if (hotjarScript.readyState === 'complete' || hotjarScript.readyState === 'loaded') { // 延迟一小段时间确保hj对象初始化完成 setTimeout(() => { window.hj && hj.globals ? resolve(hj) : reject(new Error('Hotjar脚本加载完成但未初始化')); }, 0); return; } // 监听脚本加载/失败事件 hotjarScript.addEventListener('load', () => { setTimeout(() => { window.hj && hj.globals ? resolve(hj) : reject(new Error('Hotjar脚本加载完成但未初始化')); }, 0); }); hotjarScript.addEventListener('error', () => reject(new Error('Hotjar脚本加载失败'))); }); } // 使用示例 waitForHotjarScript() .then((hj) => { const userId = hj.globals.get('userId').split('-').shift(); console.log('Hotjar用户ID:', userId); }) .catch((err) => console.error('等待Hotjar失败:', err));
为什么你之前的代码会报错?
你执行hj.globals.get('userId')时,Hotjar的异步脚本还没完成初始化——要么hj全局对象还没创建,要么hj.globals属性还未挂载,所以浏览器抛出了Cannot read property 'get' of undefined的错误。上面的Promise方案就是为了确保代码只在hj.globals完全可用后再执行。
内容的提问来源于stack exchange,提问作者Mohammad Taherian
相关产品推荐
相关产品推荐

