function debounce(func, wait = 300, immediate = false) {
  let timer, ctx;
  let later = (arg) =>
    setTimeout(() => {
      func.apply(ctx, arg);
      timer = ctx = null;
    }, wait);
  return function (...arg) {
    if (!timer) {
      timer = later(arg);
      ctx = this;
      if (immediate) {
        func.apply(ctx, arg);
      }
    } else {
      clearTimeout(timer);
      timer = later(arg);
    }
  };
}
