微任务防抖

防抖与节流

防抖

触发多次的事件都归并为一次事件在给定的时间内进行触发

document.onmousemove = _.debounce(()=> {
  console.log(1)
},
1000,
true // 首次立即执行
)

节流

在一次事件中,按给定的时间进行分段触发

document.onmousemove = _.throttle(()=> {
  console.log(1)
},1000,{
leading:false, // 首次立即执行
trailing:true // 最后一次不触发
})

宏任务和微任务

异步任务需要适当的管理。为此,ECMA 标准规定了一个内部队列 PromiseJobs,通常被称为“微任务队列(microtask queue)”(ES8 术语)。当一个 promise 准备就绪时,它的 .then/catch/finally 处理程序(handler)就会被放入队列中:但是它们不会立即被执行。当 JavaScript 引擎执行完当前的代码,它会从队列中获取任务并执行它。

每个宏任务之后,引擎会立即执行微任务队列中的所有任务,然后再执行其他的宏任务,或渲染,或进行其他任何操作。

setTimeout(() => alert("timeout"));

Promise.resolve()
  .then(() => alert("promise"));

alert("code");

code 首先显示,因为它是常规的同步调用。
promise 第二个出现,因为 then 会通过微任务队列,并在当前代码之后执行。
timeout 最后显示,因为它是一个宏任务。

微任务防抖

const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && typeof navigator !== 'undefined'

const supportsMicroTasks = isBrowser && window.Promise

function microtaskDebounce(fn) {
  let called = false
  return () => {
    if (called) {
      return
    }
    called = true
    window.Promise.resolve().then(() => {
      called = false
      fn()
    })
  }
}

const timeoutDuration = (function(){
  const longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
  for (let i = 0; i < longerTimeoutBrowsers.length; i += 1) {
    if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
      return 1;
    }
  }
  return 0;
}());

function taskDebounce(fn) {
  let scheduled = false;
  return () => {
    if (!scheduled) {
      scheduled = true;
      setTimeout(() => {
        scheduled = false;
        fn();
      }, timeoutDuration);
    }
  };
}

requestAnimationFrame(supportsMicroTasks ? microTaskDebounce : taskDebounce)


原文地址:https://www.cnblogs.com/pluslius/p/13779417.html