巴青农资商城

actionGuard.js 1.1KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. import { ref } from 'vue'
  2. /** 提交类按钮默认防抖间隔(毫秒) */
  3. export const ACTION_GUARD_DEBOUNCE_MS = 300
  4. /**
  5. * 提交/支付类操作:防抖 + 执行期间加锁(禁止重复点击)
  6. * @param {number} debounceMs 两次有效触发的最小间隔
  7. * @returns {{ locked: import('vue').Ref<boolean>, run: Function, wrap: Function }}
  8. */
  9. export function useActionGuard(debounceMs = ACTION_GUARD_DEBOUNCE_MS) {
  10. const locked = ref(false)
  11. let lastAt = 0
  12. /**
  13. * 在锁内执行异步任务;校验失败可在 task 内 return,仍会释放锁
  14. * @param {() => Promise<void|boolean>|void|boolean} task
  15. * @returns {Promise<boolean>} 是否实际执行了 task
  16. */
  17. async function run(task) {
  18. if (locked.value) return false
  19. const now = Date.now()
  20. if (now - lastAt < debounceMs) return false
  21. lastAt = now
  22. locked.value = true
  23. try {
  24. await task()
  25. return true
  26. } finally {
  27. locked.value = false
  28. }
  29. }
  30. /** 包装函数,适合直接绑 @click */
  31. function wrap(fn) {
  32. return (...args) => run(() => fn(...args))
  33. }
  34. return { locked, run, wrap }
  35. }