Next.js Discord

Discord Forum

Is it ok to have a `async` in `socket.on('event-key', async (data) => {})` ?

Answered
Virginia's Warbler posted this in #help-forum
Open in Discord
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:

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.
View full answer

17 Replies

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
So I have

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:

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
Virginia's WarblerOP
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 !!