如何优化Toast调用:用回调重试替代固定延迟检测window.globalToast
优化Toast工具函数:替换固定延迟为动态实例化检测
方案一:使用Promise监听全局属性变化(推荐)
这种方案通过监听window.globalToast的赋值操作,在它完成实例化后立即执行Toast调用,无需等待固定延迟,效率最高。
// 初始化一个Promise,用于等待globalToast完成实例化 let toastReadyPromise: Promise<void>; let toastResolve!: () => void; toastReadyPromise = new Promise(resolve => { toastResolve = resolve; }); // 重写window.globalToast的getter/setter,监听实例化完成事件 Object.defineProperty(window, 'globalToast', { set(value) { // 将实例存储到私有属性中 (window as any)._globalToast = value; // 触发Promise完成,通知所有等待的消息调用 toastResolve(); }, get() { return (window as any)._globalToast; }, configurable: true, enumerable: true }); export const showMessage = async (message: string): Promise<void> => { // 等待globalToast初始化完成 await toastReadyPromise; window.globalToast.addToast(message); };
优势
- 无不必要延迟:
globalToast一实例化,消息就会立即显示 - 可靠性高:不会因为初始化时长超过固定延迟导致消息丢失
- 代码简洁:一次监听,所有调用自动等待
方案二:递归轮询检测(无需修改初始化逻辑)
如果无法修改window.globalToast的实例化代码(比如来自第三方库),可以用短间隔轮询的方式检测实例是否存在,直到可用或达到重试上限。
export const showMessage = ( message: string, retryDelay = 100, // 每次重试间隔(毫秒) maxRetries = 30 // 最大重试次数,避免无限递归 ): void => { // 实例已存在,直接显示消息 if (window.globalToast) { window.globalToast.addToast(message); return; } // 达到重试上限,打印警告 if (maxRetries <= 0) { console.warn('Toast初始化超时,无法显示消息:', message); return; } // 递归重试 setTimeout(() => { showMessage(message, retryDelay, maxRetries - 1); }, retryDelay); };
优势
- 无需修改原有初始化逻辑,兼容性强
- 响应速度比固定1.5秒延迟更快,最多等待3秒(按默认参数)
- 有重试上限,避免内存泄漏
对比原临时方案的问题
原方案的固定1.5秒延迟存在两个核心问题:
- 不可靠:如果
globalToast初始化耗时超过1.5秒,消息仍然无法显示 - 体验差:如果初始化很快完成,用户仍需等待1.5秒才能看到Toast
上述动态检测方案完美解决了这两个问题,既保证可靠性,又提升了用户体验。
内容的提问来源于stack exchange,提问作者Yang Liu
相关产品推荐
相关产品推荐

