如何避免多次调用notifyError时内部setTimeout被覆盖?
问题修复方案
核心问题说明
setTimeout 每次调用都会生成独立的定时器实例,本身不存在覆盖逻辑。你遇到的现象本质是定时器回调的删除规则错误:所有定时器触发时都统一删除通知数组的最后一项,先触发的定时器会误删后新增的通知,和“每个定时器仅删除对应本次调用生成的通知”的预期不符。
修复代码
修改核心逻辑为给每个新增通知绑定唯一标识,定时器触发时匹配标识删除对应通知即可:
export function notifyError(message) { // 生成当前通知唯一标识,也可以替换为uuid等专业唯一值生成方案 const notificationId = Date.now() + Math.random() // 将标识和消息一起存入通知数组 notifications.push({ id: notificationId, message: message }) // 原生setTimeout每次调用都会创建新实例,不需要额外处理 setTimeout(() => { // 匹配当前标识的通知下标进行删除,不会影响其他通知 const targetIndex = notifications.findIndex(item => item.id === notificationId) if (targetIndex > -1) { notifications.splice(targetIndex, 1) } }, 3000) }
可选扩展:手动管理定时器
如果需要支持批量清空未触发的通知(比如页面卸载、组件销毁场景),可以额外存储所有定时器id,按需统一清理:
// 全局存储所有未触发的定时器id const errorTimerIds = [] export function notifyError(message) { const notificationId = Date.now() + Math.random() notifications.push({ id: notificationId, message }) const timerId = setTimeout(() => { const targetIndex = notifications.findIndex(item => item.id === notificationId) if (targetIndex > -1) { notifications.splice(targetIndex, 1) } // 触发后移除自身的定时器id记录 const timerIndex = errorTimerIds.indexOf(timerId) if (timerIndex > -1) { errorTimerIds.splice(timerIndex, 1) } }, 3000) errorTimerIds.push(timerId) } // 导出批量清理方法 export function clearAllErrorNotifications() { errorTimerIds.forEach(timerId => clearTimeout(timerId)) errorTimerIds.length = 0 notifications.length = 0 }
内容的提问来源于stack exchange,提问作者Philx94
相关产品推荐
相关产品推荐

