/** 与首页 guardPage 使用的全页互斥 key 一致 */ export const PAGE_ACTION_LOCK_KEY = '__page__' /** * 全页「同一时间只响应一次点击」:任务进行中再次点击直接忽略(无提示)。 * timeoutMs:避免底层 Promise 永不结束导致永久锁死。 */ export function createTapGuard() { const busy = Object.create(null) const tokenByKey = Object.create(null) return { run(key, fn, timeoutMs = 25000) { if (busy[key]) { return Promise.resolve() } busy[key] = true const token = (tokenByKey[key] = (tokenByKey[key] || 0) + 1) let timeoutId if (timeoutMs > 0) { timeoutId = setTimeout(() => { if (busy[key] && tokenByKey[key] === token) { busy[key] = false try { uni.showToast({ title: '操作超时,请重试', icon: 'none', duration: 2000 }) } catch (e) {} } }, timeoutMs) } let p try { p = Promise.resolve().then(fn) } catch (e) { if (timeoutId) clearTimeout(timeoutId) busy[key] = false return Promise.reject(e) } return p.finally(() => { if (timeoutId) clearTimeout(timeoutId) if (tokenByKey[key] === token) { busy[key] = false } }) } } }