When I click ‘CLICK ME’ repeatedly and quickly, why is there a possibility that console.log(`===${innerCount}.2`);
is executed earlier over console.log(`===${innerCount}.1`);
Here is the CodeSandBox: https://codesandbox.io/s/loving-blackburn-v4k5y4?file=/src/App.js:651-666
throttle
is from lodash
.
let count = 0;
const App = () => {
const throttledFetchData = throttle(async (innerCount) => {
const result = await callApi();
console.log(`===${innerCount}.1`);
return result;
}, 100);
const handleClick = throttle(async (e: any) => {
count++;
const innerCount = count;
const result = await throttledFetchData(innerCount);
console.log(`===${innerCount}.2`);
}, 50);
return (
<div className='container' onClick={handleClick}>
CLICK ME
</div>
);
}
Why wrapping two throttle?
Because it was a mistake,I’m stuck with the order problem when I debug.
Why did not reproduce the problem?
It only appears when click very quickly.
2
Answers
Don’t know the entire context, but you can try using "useCallback" something like this
The useCallback hook to memoizes the handleScroll and throttledFetchData functions. This helps prevent unnecessary re-rendering of the component and ensures that we are always working with the latest version of these functions.
I also added a countRef variable to keep track of the number of times handleScroll is called. This is done using the useRef hook, which creates a mutable variable that persists across re-renders.
Also, updated the event listener to listen for the "onScroll" event instead of the "onClick" event
The second
throttle
is not relevant, the cause of the issue is the behaviour of the firstthrottle
d function. In particular,You can see this more clearly when you return the
innerCount
, not thecallApi()
result, from the throttled function, to identify which promisehandleClick
was waiting for:So what’s happening when
handleClick
is called twice in quick succession:handleClick
invocation callsthrottledFetchData(1)
callApi()
throttledFetchData(1)
andawait
suspends the execution ofhandleClick
handleClick
invocation callsthrottledFetchData(2)
await
in the secondhandleClick
suspends execution until that old promise is settledcallApi()
callApi()
promise fulfills and resumes execution===1.1
is logged and1
is returned (fulfilling the promise)handleClick
is resumed and logs===1.2 after 1
handleClick
is resumed and logs===2.2 after 1
callApi()
promise fulfills and resumes execution===2.1
is logged and2
is returned, but nobody is waiting for that promise