Is it ok to have a `async` in `socket.on('event-key', async (data) => {})` ?
Answered
Virginia's Warbler posted this in #help-forum
Virginia's WarblerOP
Would it be wrong or alright to have an
async
function as an event listener?Answered by Rapidement
Can you try that:
I think that the problem is: when the socket listener is registered, it closes over the value of dependency at that exact moment, usually undefined.
Even if dependency gets updated later via setDependency, the closure inside socket.on(...) doesn't see it.
const dependencyRef = useRef();
const [dependency, setDependency] = useState();
useEffect(() => {
dependencyRef.current = dependency;
}, [dependency]);
socket.on("key", (data) => {
console.log("inside event", dependencyRef.current); // always up-to-date
someFunction().then(() => {
console.log("after await", dependencyRef.current); // still up-to-date
anotherFunction();
});
});
const anotherFunction = async () => {
console.log("in anotherFunction", dependencyRef.current); // also up-to-date
};
I think that the problem is: when the socket listener is registered, it closes over the value of dependency at that exact moment, usually undefined.
Even if dependency gets updated later via setDependency, the closure inside socket.on(...) doesn't see it.
17 Replies
Yeah, I think it's totally fine to use
You can use
Just one thing to keep in mind: Socket.IO doesn’t automatically catch errors thrown inside async handlers.
So if something fails (like an
Please feel free to tell me if I'm wrong.
async
in a socket.on('event', async (data) => { ... })
.You can use
await
inside just like in any other async function.Just one thing to keep in mind: Socket.IO doesn’t automatically catch errors thrown inside async handlers.
So if something fails (like an
await
that throws) and you don’t wrap it in a try/catch
, it might crash your app or log some weird warnings.Please feel free to tell me if I'm wrong.
@Rapidement Yeah, I think it's totally fine to use `async` in a `socket.on('event', async (data) => { ... })`.
You can use `await` inside just like in any other async function.
Just one thing to keep in mind: Socket.IO doesn’t automatically catch errors thrown inside async handlers.
So if something fails (like an `await` that throws) and you don’t wrap it in a `try/catch`, it might crash your app or log some weird warnings.
Please feel free to tell me if I'm wrong.
Virginia's WarblerOP
Hello, are you still there?
I am now very troubled by a related problem, I wonder if you can help
I am now very troubled by a related problem, I wonder if you can help
Virginia's WarblerOP
So I have
then
the
const [dependency, setDependency] = useState(); // This is actually in a provider that wraps around the whole app. This is set elsewhere soon after app starts.
then
socket.on(`key`, (data) => {
console.log({dependency}); // Somethere present, sometimes undefined
someFunction().then( () => {
console.log({dependency}); // Always undefined
anotherFunction();
});
});
the
anotherFunction
const anotherFunction = async () => {
console.log({dependency}); // Always undefined
}
So I am so stuck, because I am not able to obtain
dependency
@Virginia's Warbler So I am so stuck, because I am not able to obtain `dependency`
Can you try that:
I think that the problem is: when the socket listener is registered, it closes over the value of dependency at that exact moment, usually undefined.
Even if dependency gets updated later via setDependency, the closure inside socket.on(...) doesn't see it.
const dependencyRef = useRef();
const [dependency, setDependency] = useState();
useEffect(() => {
dependencyRef.current = dependency;
}, [dependency]);
socket.on("key", (data) => {
console.log("inside event", dependencyRef.current); // always up-to-date
someFunction().then(() => {
console.log("after await", dependencyRef.current); // still up-to-date
anotherFunction();
});
});
const anotherFunction = async () => {
console.log("in anotherFunction", dependencyRef.current); // also up-to-date
};
I think that the problem is: when the socket listener is registered, it closes over the value of dependency at that exact moment, usually undefined.
Even if dependency gets updated later via setDependency, the closure inside socket.on(...) doesn't see it.
Answer
So why would updated refs be seen in closures, but not states?
Does this have anything to do with "stale state closure"?
Virginia's WarblerOP
This is the theory, right? https://youtu.be/7yw_D3h4xSo?si=Yee4vl5DEHOvoE8o
Virginia's WarblerOP
I gone passed that hurdle. Your solution worked and I understood it now
One more related Q please:
someFunction().then(() => {
anotherFunction();
});
Is it ok or not ok to make the function inside
.then()
async?ie: Is it ok to do this?
someFunction().then(async () => {
await anotherFunction();
});
useState
values are immutable in a closure,useRef if you access the state inside a function (like a socket.on() or a setTimeout), that function only "remembers" the value of state at the moment it was created.useRef
values are mutable and don't trigger re-renders, but their .current can be changed, and closures always see the current value.Virginia's WarblerOP
Thank you v much again
@Virginia's Warbler Thank you v much again
Np, do not forget to mark the message as a solution !!