使用window.location.href唤起应用时如何捕获报错并实现跳转下载逻辑
解决方案
核心原理
scheme唤起失败的报错属于浏览器的系统级异常,不会暴露给JS执行上下文,因此常规的try/catch、Promise.catch都无法捕获。行业通用的实现方案是基于页面失焦/超时检测判断是否唤起成功,对应触发下载逻辑。
具体实现步骤
- 监听页面的
visibilitychange和blur事件,页面触发失焦就代表唤起成功、用户已切到客户端,此时清除兜底的下载定时器 - 设置1.5s~2s的延时定时器,超时后如果页面仍处于激活状态,判定为未安装目标应用,自动跳转下载页
- 触发scheme唤起时优先用隐藏iframe加载scheme地址,不要直接修改
window.location.href,避免当前页面被异常覆盖
代码示例
function openApp(downloadUrl, schemeUrl) { let timer = null; const timeout = 1500; // 可根据场景调整,建议1.5-2s // 页面失焦回调:唤起成功则清除定时器 const onBlur = () => { if (timer) { clearTimeout(timer); timer = null; } window.removeEventListener('blur', onBlur); window.removeEventListener('visibilitychange', onVisibilityChange); }; const onVisibilityChange = () => { if (document.hidden) onBlur(); }; window.addEventListener('blur', onBlur); window.addEventListener('visibilitychange', onVisibilityChange); // 兜底逻辑:超时未唤起则跳下载 timer = setTimeout(() => { window.location.href = downloadUrl; window.removeEventListener('blur', onBlur); window.removeEventListener('visibilitychange', onVisibilityChange); }, timeout); // 用iframe触发scheme,避免当前页面跳转异常 const iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = schemeUrl; document.body.appendChild(iframe); setTimeout(() => document.body.removeChild(iframe), 3000); }
兼容性说明
- 部分安卓定制浏览器会拦截scheme唤起,或者弹出是否允许打开的确认弹窗,这类场景可以适当调长超时时间到2.5s,避免用户还没点击确认就触发下载
- iOS 15+ Safari如果scheme未注册,会弹出系统级的无效地址提示,属于系统限制,目前没有完美规避方案
内容的提问来源于stack exchange,提问作者DAVID
相关产品推荐
相关产品推荐

