2

I have a base async function that returns a Promise

function asyncFoo(): Promise<void> {
  return new Promise<void>((resolve, reject) => {
    // I'm using here a setTimeout to fake async flow, in reality I'm making a server call
    setTimeout(() => {
      resolve();
    }, 5000);
  });
}

I can use my method

const promise = asyncFoo();
promise.then(() => {
  console.log('Hello');
});

However if I debounce my function, the result function doesn't return anything, and I can't wait for it to resolve

const debounceFoo = _.debounce(asyncFoo, 100);
debounceFoo(); // undefined
// I would like to do something like
// debounceFoo().then(...) this will not work

How can I debounce the events (aggregate them) that happen during the debounce-time, then execute my asyncFoo(). And finally, act on its resolve callback?

Gil Epshtain
  • 8,670
  • 7
  • 63
  • 89
  • @jfriend00 - I have a working flow in which I'm using a method that returns a promise. This method is being called too often. I want to denounce its execution. Then act on the resolved promise. – Gil Epshtain May 23 '22 at 13:51
  • Do you want `_.debounce(() => asyncFoo().then(console.log), 100);`? Or do you really want to write `debounceFoo().then(console.log)`? – Bergi May 23 '22 at 14:03
  • This question has nothing to do with the related question that linked in the duplication panel. Please consider to Reopen this question – Gil Epshtain May 24 '22 at 20:08

2 Answers2

2

You can use promise to do this:

const debounceAsync = (func, wait) => {
  let timerID = -1;

  return (...args) => {
    clearTimeout(timerID);

    const promiseForFunc = new Promise((resolve) => {
      timerID = setTimeout(resolve, wait);
    });

    return promiseForFunc.then(() => func(...args));
  };
};

const debounceFoo = debounceAsync(asyncFoo, 100);

debounceFoo().then(() => {
  console.log('Hello');
});

The debounced function which return by lodash debounce usually return undefined before first time your func was invoked.

https://github.com/lodash/lodash/blob/2f79053d7bc7c9c9561a30dda202b3dcd2b72b90/debounce.js#L184-L206

ryan.c
  • 85
  • 8
  • Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! No need for nesting here, one `new Promise` around the `setTimeout` is enough. – Bergi May 23 '22 at 14:30
  • 1
    Thank you @Bergi, I remove the unnecessary nested promise. – ryan.c May 23 '22 at 14:38
-1

Not sure about lodash's implementation but you can write your own debounce as this.

function debounce(func, timeout) {
  let timer;

  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, args);
    }, timeout);
  };
}

function asyncBar() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log("Hi");
      resolve();
    }, 4000);
  });
}

const foo = debounce(async () => asyncBar(), 5000);

foo();

Orgil
  • 691
  • 7
  • 16
  • Thank you very much. But the `foo()` function return `void/undefined`. I'm looking for `foo()` that returns a Promise – Gil Epshtain May 23 '22 at 14:02