Reputation: 23
updatePixelBuffer(x, y) {
console.log("cleared from update", this.state.pixelRefreshTimer);
window.clearTimeout(this.state.pixelRefreshTimer);
let pixelRefreshTimer = window.setTimeout(() => {
console.log("from timer", pixelRefreshTimer);
this.triggerPixelRefresh();
}, 3000);
console.log("set timer", pixelRefreshTimer);
this.setState({
pixelRefreshTimer: pixelRefreshTimer,
});
// store operation in buffer and perform visual draw
}
triggerPixelRefresh() {
console.log("cleared from refresh", this.state.pixelRefreshTimer);
window.clearTimeout(this.state.pixelRefreshTimer);
// update data structure with operations in buffer
}
Most of the time updatePixelBuffer is called on it's own multiple times since I'm using it to store drawing operations before I batch update them on the data structure, I'm allowing the user to visualize the drawing operations live (even though the data structure hasn't updated them yet).
My dilemma starts when I want to call triggerPixelRefresh() right after making a call to updatePixelBuffer(x, y). The timer should not set off after this call.
updatePixelBuffer(1, 2);
triggerRefresh();
Since setState is asynchronous, I don't know how to guarantee that window.clearTimeout in triggerPixelRefresh() will clear the newly set timer in updatePixelBuffer if they are called one after the other. I'm not sure what pattern to use to guarantee this.
updatePixelRefresh sets up a timer so that if triggerPixelRefresh is not called upon later, it will be called. It's to guarantee that the operations in the buffer are made at a later time. triggerRefresh needs to cancel that timer and immediately update the data structure with the stored operations. I need to prevent the refresh from being called upon at unpredictable times.
I technically could just directly modify the state to make them run synchronously, but I would prefer not to.
Upvotes: 0
Views: 628
Reputation: 669
It should be very relatively easy to get to what you are looking for, employ callback hooks in your operation. So instead of trying to force synchronicity by calling one function after the other (even though this works in everyday's work it is still technically not guaranteed because the OS/Runtime/Hardware can decide to go attend some more important work before running your next function) so I'd say rather have triggerPixelRefresh
as a function input to updatePixelBuffer
that way you have more control on when to call it.
updatePixelBuffer(x, y,triggerRefreshHandler) {
...call triggerRefresherHandler at the appropriate time here
}
Then you can do
updatePixelBuffer(1, 2,triggerRefresh);
It's probably not too critical, but I notice that you are using quite a lot of window object, I'm just curious if this will not cause any issues since React uses a Virtual DOM and SPA's normally will also run in server when you want server rendering performance and in an environment like NodeJS window would not exist.
Happy coding
Upvotes: 0
Reputation: 15271
setState(state,callback)
overload exists for that: to guarantee callback
being called after the state has been changed.
that being said, you could transform your updatePixelBuffer
to return a Promise
which resolves when callback
has been called.
also, you could have your triggerPixelRefresh
also return a promise that resolve immediately.
at the end, wrap them both in function, have function expose triggerPixelRefreshPromise
resolve method which you can call afterwards.
in the end, wrap both promises in Promise.race([p1,p2])
.
what Promise.race(p1,p2)
does is that it will resolve to whichever of p1,p2
promises resolve first (in other words, timeout or your direct call).
take a look at this also: Understanding promise.race() usage
Upvotes: 1