The function to wrap. Each call to the wrapper will result in a call to this function.
Suppose you have a search function like the following that, based on the number or results, may take 1 second or 10 ms to execute:
const search = (signal: AbortController, criteria: string) => fetch(`/api/search?q=${criteria}`, { signal });
If the user type in "he" it takes one second to resolve. But the user keeps writing so he enters "hello world" before the initial search for "he" is complete.
The search for "hello world" takes only 10 ms (as it's far more specific) so you receive the
result immediatly and, in your react component, do setResults(results)
.
But what happens now when the result for "he" finally arrives? The search that started earlier
is resolving latest and you end up doing setResults(results)
again, only this time the results are
from an earlier query.
Generated using TypeDoc
When working with UIs it's common to have a situation when an async function is invoked in response to an UI event. In this scenarion race conditions between calls may occur. The easiest way to resolve these conditions is to ignore/abort any result that is not generated by the latests invocation of the async function.
This utility takes an async function and ensure that the caller will always receive the result obtained by the latest call to the function ignoring any intermediate result.
Keep in mind that in most situations a debounce is not enough to replace this utility. The debounce can only delay the execution and prevent results before the function execution while this wrapper also handles the time frame to execute the async operation.
This utility also provides to the decorated function an AbortController instance that should be used to cancel intermediate pending calls if possible.