WebSocket return undefined after fetching user, but console.log prints the user

Viewed 19

I've been working with a websocket to fetch users.

I open the connection and send the messages to get the data, but if I want to return that user and use it elsewhere, I get undefined, but when running console.log inside the function, it gives me the user.

Here is my code :

export function fetchUser(id: number) {
  const connection = generateConnection();
  connection.onopen = () => {
    connection.send(
      JSON.stringify(
        '{"msg":"connect","version":"1","support":["1","pre2","pre1"]}',
      ),
    );
    connection.send(
      JSON.stringify(
        `{"msg":"method","id":"1","method":"Users.getUser","params":[${id}]}`,
      ),
    );
  };
  connection.on('message', async (event) => {
    const data = event.toString();
    if (data[0] == 'a') {
      const a = JSON.parse(JSON.parse(data.substring(1))[0]);
      if (a.msg == 'result') {
        if ('error' in a) {
          console.log(a.error.error);
          connection.close();
          return null;
        } else {
          let user= a.result;
          console.log(user) // returns the user

          return user; // return undefined
          
        }
      }
    }
  });
}
console.log(fetchUser(1));
2 Answers

Given the details I have this should be at least close to something functional. I've added a number of comments where the exist code doesn't make sense.

const state = {
    isReady: false,
}
const connection = generateConnection();
const sendMsg = (msg) => connection.send(JSON.stringify(msg))

connection.onopen = () => {
    sendMsg({"msg": "connect", "version": "1", "support": ["1", "pre2", "pre1"]})
    state.isReady = true; // not sure if this is true yet
};

export async function fetchUser(id: number) {
    if (!state.isReady) {
        throw new Error("Not ready yet")
    }
    sendMsg({"msg": "method", "id": "1", "method": "Users.getUser", "params": [id]})
    return new Promise((resolve, reject) => {
        connection.once('message', async (event) => {
            // why event.toString()? what is it? Is this JSON data?
            const data = event.toString();
            // what are you doing here?
            if (data[0] === 'a') {
                // this much be wrong and has something to do with event.toString()
                const a = JSON.parse(JSON.parse(data.substring(1))[0]);
                // this is likely wrong too ie should be something like a.result && a.error
                if (a.msg === 'result') {
                    if ('error' in a) {
                        console.log(a.error.error);
                        return resolve(null)
                    }
                    let user = a.result;
                    console.log(user) // returns the user
                    return resolve(user); // return undefined
                }
            }
        });
    })
}

fetchUser(1)
    .then((user) => console.log(user))
    .catch((err) => console.log(err))

I got inspired from your code and got something to work:

import { generateConnection } from './generate-connection';
const connection = generateConnection();
export async function fetchUser(id: number) {
  return new Promise(function (resolve) {
    console.log('Opening connection...');
    connection.onopen = () => {
      connection.send(
        JSON.stringify(
          '{"msg":"connect","version":"1","support":["1","pre2","pre1"]}',
        ),
      );
      console.log('Connection opened');
      console.log('Sending message...');
      connection.send(
        JSON.stringify(
          `{"msg":"method","id":"1","method":"Users.getUser","params":[${id}]}`,
        ),
      );
    };
    connection.on('message', async (event) => {
      // yes it gives json data;
      const data = event.toString();
      if (data[0] == 'a') {
        // when the response come it's a string with a prefix 'a'
        const a = JSON.parse(JSON.parse(data.substring(1))[0]);
        if (a.msg == 'result') {
          if ('error' in a) {
            console.log(a.error.error);
            return null;
          } else {
            resolve(a.result);
            connection.close();
          }
        }
      }
    });
    connection.on('error', function (error) {
      console.log('Connection Error: ' + error.toString());
    });
    connection.on('close', function () {
      console.log('echo-protocol Connection Closed');
    });
  });
}

fetchUser(1).then((data) => console.log(data.name));

The problem with one , is when I loop , I only get the first user


for (let i = 0; i < 10; i++) {
  const data: any = await fetchUser(i);
  console.log(data.name);
}

gives :

Opening connection
connection opened
sending message
Jack
Opening connection
connection opened
sending message

and it exits...

Related