46 lines
1.2 KiB
JavaScript
46 lines
1.2 KiB
JavaScript
|
|
/** 与首页 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
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|