I need to update a database after an event is emitted from contract
. I'm concerned about instances where the contract
emits another SomeEvent
before the DB operations finish, causing the useEffect
to retrigger before the first update is complete. Is this a genuine concern and how is it usually handled?
useEffect(() => {
contract.on("SomeEvent", (_a, _b) => {
...perform DB operations here!
})
/* Handle unmounts */
return () => {
contract.removeAllListeners("SomeEvent");
}
}, [])
CodePudding user response:
One way to do it is to make the event listener a promise chain, so the next event only runs after the previous event finishes (by awaiting the asychronous function).
useEffect(() => {
let queue = Promise.resolve();
contract.on("SomeEvent", (_a, _b) => {
queue = queue.then(async () => {
// perform async DB operations here!
await dbOperation(_a, _b);
});
});
/* Handle unmounts */
return () => {
contract.removeAllListeners("SomeEvent");
}
}, [])
CodePudding user response:
@Sebastian removed a comment that suggested the technical term "race condition". I found this article that helped clarify what my problem was (while also shedding light on what @phil points out). I tinkered around and found that 1) the useEffect
will complete all event calls just not in the order they were received and 2) you can retrieve the latest request using a structure similar to the one found here