Electron自定义协议未注册时调用报错,如何检测处理?
自定义协议唤起Electron应用:未安装时避免错误弹窗并检测状态
问题背景
通过自定义协议xyz://唤起自研Electron应用时,应用已安装可正常唤起;但未安装时,浏览器会弹出“Module is not found”错误弹窗,且try-catch无法拦截该浏览器级错误。需求是提前检测协议是否注册(即应用是否安装),未注册时显示提示或禁用唤起按钮。
已配置信息:
- Electron的
package.json协议配置:
"protocols": { "name": "electron-deep-linking", "schemes": [ "xyz" ] },
- Electron端协议注册代码:
app.setAsDefaultProtocolClient('xyz');
- 原网页唤起代码:
window.location.assign("xyz://");
解决方案
浏览器没有直接检测自定义协议注册状态的API,可通过间接判断浏览器行为实现检测:
方法1:基于页面焦点变化的检测
当协议可被处理时,唤起应用会使浏览器失去焦点;若协议未注册,浏览器焦点不会变化。结合定时器判断:
function openElectronApp() { const start = Date.now(); // 尝试唤起应用 window.location.assign('xyz://'); // 500ms后检测焦点状态 setTimeout(() => { // 若时间差小于1000ms且页面仍处于焦点,判定协议未注册 if (Date.now() - start < 1000 && document.hasFocus()) { alert('应用未安装,请先安装后重试'); // 禁用唤起按钮示例: // document.getElementById('your-button-id').disabled = true; } }, 500); }
方法2:iframe加载+错误回调+定时器兜底
创建隐藏iframe加载协议,未注册时会触发onerror事件,同时结合页面焦点变化和定时器避免误判:
function checkAndLaunchApp() { const iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = 'xyz://'; let isAppLaunched = false; // 唤起成功时页面失焦,标记为已启动 window.addEventListener('blur', () => { isAppLaunched = true; }, { once: true }); // 加载错误且未启动应用,判定未安装 iframe.onerror = () => { if (!isAppLaunched) { alert('应用未安装,请先安装后重试'); } document.body.removeChild(iframe); }; // 1秒后兜底判断 setTimeout(() => { if (!isAppLaunched) { alert('应用未安装,请先安装后重试'); } document.body.removeChild(iframe); }, 1000); document.body.appendChild(iframe); }
注意事项
- 定时器时长可根据系统响应速度调整(推荐500-1000ms),避免因系统卡顿导致误判。
- 部分浏览器可能拦截自定义协议唤起,可配合引导用户允许相关操作。
- 若需页面加载时就检测状态,可在
DOMContentLoaded事件中调用上述检测逻辑,提前设置按钮禁用状态。
内容的提问来源于stack exchange,提问作者Himesh Aadeshara
相关产品推荐
相关产品推荐

