Socket.io and Async Not Returning Values

Viewed 573

I have a async client function that returns whether or not a username is taken. I am using socket.io for sending packets of data, and I am having trouble finding out what the issue is.

This is the function (Browser):

let socket = io();
async function createAccount(username, password){
    socket.emit('create account', {username:username, password:password});

    let res;

    await socket.on('create account return', (data) => {
        res = data.failed;
    });
    return res;
};

Here is my test script, which should log true if the username is valid, and false otherwise:

createAccount('bagel03', '12345').then((val)=>console.log(val));

Instead, I always get undefined, but if I change the return statement in the createAccount function to:

return true;

It works and logs true.

I am new to async await (this is my first project with it), and nothing online has been helping. What is the problem?

EDIT: Here is the server code (Node.js):

const io = require('socket.io')(server,{ pingTimeout: 4000, pingInterval: 4000 })

io.sockets.on('connect',  socket =>{
    //account stuff
    socket.on('create account',  data =>{
        if(!isUsernameTaken(data.username)){
            id = addAccount(data);
            socket.emit('create account return',{failed:false})
        }else socket.emit('create account return', {failed:true})

    });
});
2 Answers

I think you are not using The websocket object in a right way.
every time you call createAccount you add a handler to 'create account return' event. For example, if you call createAccount 3 times, you have 3 handlers on 'create account return'.

Events are also async and whenever they are triggered ,event Handler will be called.
this is the simplest way that you can use it ,but it's better you wrap it in a class

let socket = io();
function createAccount(username, password){
    socket.emit('create account', {username:username, password:password});

};

function myHandler(data) {
   console.log(data.failed);
}

socket.on('create account return', myHandler);

You can't use await on an even listener. If you want to write your createAccount in order to be called with await you just need to make it to return a Promise. Something like:

let socket = io();
function createAccount(username, password) {
  return new Promise((resolve, reject) => {
    socket.emit('create account', {username:username, password:password});

    socket.once('create account return', (data) => resolve(data.failed));
  });
};
Related