utils.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /**
  2. * 启动一个微任务。
  3. *
  4. * 该函数旨在兼容不同环境下的微任务调度。微任务是一种在主任务(如事件循环中的回调)之后,但在下一次渲染之前执行的JavaScript任务。
  5. * 它们对于异步编程和性能优化非常重要。此函数尝试使用三种不同的方法来调度微任务,取决于环境的支持情况。
  6. *
  7. * @param {Function} callback - 待执行的微任务回调函数。
  8. */
  9. export function startMicroTask(callback) {
  10. // 如果队列微任务是可用的,直接使用队列微任务的方法来调度回调。
  11. if (typeof queueMicrotask === 'function') {
  12. queueMicrotask(callback)
  13. } else if (typeof MutationObserver === 'function') {
  14. // 如果MutationObserver可用,使用它来创建一个微任务。
  15. // 这是一种旧的兼容性方法,因为MutationObserver在较早的浏览器版本中就已经支持。
  16. const node = document.createElement('div')
  17. const observer = new MutationObserver(callback)
  18. observer.observe(node, { childList: true })
  19. node.textContent = 'xfjpeter'
  20. } else {
  21. // 如果以上两种方法都不可用,退回到使用setTimeout来模拟微任务。
  22. // 这是最后的选择,因为setTimeout不是真正的微任务,但它可以在不支持微任务的环境中提供类似的功能。
  23. setTimeout(callback, 0)
  24. }
  25. }
  26. /**
  27. * 函数节流器。
  28. * 通过限制函数调用的频率,防止在高频率事件(如窗口滚动或鼠标移动)中过多调用给定的函数,从而优化性能。
  29. *
  30. * @param {Function} fn 要节流的函数。
  31. * @param {number} delay 延迟的毫秒数,在这段时间内只能调用一次给定的函数。
  32. * @returns {Function} 返回一个新的节流函数,它将控制原始函数的调用频率。
  33. */
  34. /**
  35. * 函数节流器
  36. * @param {Function} fn 要节流的函数
  37. * @param {number} delay 延迟的毫秒数
  38. * @returns {Function} 返回节流后的函数
  39. */
  40. export function throttle(fn, delay) {
  41. // 用于存储定时器ID
  42. let timeoutId
  43. // 用于记录上一次函数执行的时间
  44. let lastExecuted = 0
  45. // 返回一个节流函数
  46. return function () {
  47. // 保存当前上下文和参数
  48. const context = this
  49. const args = arguments
  50. // 获取当前时间
  51. const now = Date.now()
  52. // 计算剩余时间
  53. const remaining = delay - (now - lastExecuted)
  54. // 实际执行函数的内部函数
  55. function execute() {
  56. lastExecuted = now
  57. // 在当前上下文中调用原始函数,并传入参数
  58. fn.apply(context, args)
  59. }
  60. // 如果剩余时间小于等于0,表示可以执行函数
  61. if (remaining <= 0) {
  62. // 如果存在定时器,则清除定时器
  63. if (timeoutId) {
  64. clearTimeout(timeoutId)
  65. timeoutId = null
  66. }
  67. // 执行函数
  68. execute()
  69. } else {
  70. // 如果不存在定时器,则设置定时器
  71. if (!timeoutId) {
  72. timeoutId = setTimeout(() => {
  73. timeoutId = null
  74. // 执行函数
  75. execute()
  76. }, remaining)
  77. }
  78. }
  79. }
  80. }
  81. /**
  82. * 函数防抖动封装。
  83. * 函数防抖(debounce)是指在事件被触发n秒后,才执行回调,如果在这n秒内事件又被触发,则重新计时。
  84. * 主要用于限制函数调用的频率,常用于输入事件处理函数(如输入框的keyup事件)和窗口大小调整事件等。
  85. *
  86. * @param {Function} fn 需要被延迟执行的函数。
  87. * @param {number} delay 延迟执行的时间,单位为毫秒。
  88. * @returns {Function} 返回一个经过防抖动处理的函数。
  89. */
  90. export function debounce(fn, delay) {
  91. // 用于存储定时器的变量
  92. let timer = null
  93. // 返回一个封装函数
  94. return function () {
  95. // 如果定时器存在,则清除之前的定时器
  96. if (timer) clearTimeout(timer)
  97. // 设置新的定时器,延迟执行原函数
  98. timer = setTimeout(() => {
  99. // 使用apply确保函数在正确的上下文中执行,并传递所有参数
  100. fn.apply(this, arguments)
  101. }, delay)
  102. }
  103. }