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
|
||
}
|
||
})
|
||
}
|
||
}
|
||
}
|