如何在SvelteKit应用中更早触发客户端SDK导入以规避竞态条件
解决方案
问题的核心是hooks.client.ts的初始化时机仍晚于App B发送消息的时间,要彻底规避竞态条件,你可以从更早的页面加载阶段入手,以下是两种可靠方案:
方案1:直接在入口HTML中提前加载SDK
这是最彻底的方式,HTML的<head>脚本会在SvelteKit应用初始化前执行,完全避免消息错过的可能。
- 打开
src/app.html文件,在<head>标签内添加SDK的CDN脚本(优先使用官方提供的CDN链接,或unpkg/jsdelivr这类公共CDN):
<head> <!-- 原有meta、样式等内容 --> <script src="https://unpkg.com/@owlbear-rodeo/sdk@latest/dist/obr.min.js"></script> </head>
- 页面加载时会优先初始化SDK的消息监听器,确保不会漏过App B发送的
OBR_READY事件。 - 后续在SvelteKit代码中(如hooks、组件),直接使用全局的
window.OBR对象即可,无需再通过import导入:
// src/hooks.client.ts import type { ClientInit } from '@sveltejs/kit'; export const init: ClientInit = async () => { console.info("Initializing iframe app.") window.OBR.onReady(() => console.log("It works.")); };
方案2:提前捕获消息并缓存,等SDK加载后复用
如果需要保留npm包的导入方式,可在页面最早期手动监听message事件,缓存OBR_READY消息,待SDK加载完成后再触发逻辑:
- 在
src/app.html的<head>中添加内联脚本,提前监听并缓存消息:
<head> <!-- 原有内容 --> <script> // 缓存OBR_READY消息 let cachedObrReadyMsg = null; window.addEventListener('message', (e) => { if (e.data?.id === 'OBR_READY') { cachedObrReadyMsg = e; } }); // 给SDK的onReady打补丁,缓存消息存在时直接触发回调 window.addEventListener('load', () => { if (window.OBR && cachedObrReadyMsg) { const originalOnReady = window.OBR.onReady; window.OBR.onReady = (callback) => { originalOnReady(callback); // 若已捕获消息,立即执行回调 callback(); }; } }); </script> </head>
- 之后正常在
hooks.client.ts中导入SDK并注册onReady回调即可,即使消息在SDK加载前发送,缓存的消息也会触发回调。
内容的提问来源于stack exchange,提问作者Mackie Messer
相关产品推荐
相关产品推荐

