简体   繁体   中英

WebSocket Response Function Execution

I have a code however the problem with it is that function getip() doesn't execute first. I haven't coded in Javascript much so I don't really know what's going on. I want the console.log('connected!') to execute after the function getip() has fully completed.

I would appreciate if someone would make the changes required for this to happen with some brief explanation if possible.

(async function getip() {
    var responses = [];
    var ips = [ "IP1", "IP2" ]
    var length = ips.length
    for (var i = 0; i < length; i++) {
        (async function() {
            var ws = new WebSocket('ws://' + ips[i] + ':80');
            await new Promise(function(res) {
                var timeout = setTimeout(function() {
                                console.log("Socket connection timeout", ws.readyState);
                                console.log(ws.url);
                                if (ws.readyState == 3){
                                    responses.push('connected')
                                } else {
                                    responses.push('not connected')
                                }
                                ws.close();
                },5000);
            });
        })();
    }
})();

console.log('connected!')

There are a couple of things happening:

The getip function is asynchronous, meaning it will not block other code from running while it is executing. This causes the console.log('connected') to be called because of the asynchronous nature.

Your Promise doesn't call res anywhere. That means that the promise will never resolve and therefor, your await will never stop waiting.

In the setTimeout in your promise you're looking for the readyState on the web socket instance. Currently what you're checking is if that state is 3 , which means closed, which it will (probably) not be, because you just opened the web socket. Instead, close the connection and reject the promise, saying that the promise has failed.

Use the onopen and onerror events to monitor if the web sockets has successfully opened or when an error occurs. In the onopen function call resolve to successfully close the promise. In the onerror callback reject the promise and pass some data to it so you can read the error log. In both cases, clear the timeout.

Instead of await -ing each Promise , collect all of them in a single array and use either Promise.all() to await the array of promises. This will ensure that all web sockets are opened in parallel. When everything goes right, the console.log('connected') will log to the console. Otherwise, if an error was produced by one of the promises, it will log an error.

This topic is quite difficult to grasp and will need some practice to get that click moment.

The example below uses all practices described above. Examine it and feel free to ask any follow-up questions if you have them.

async function getip() {
  const ips =  ["IP1", "IP2"];
  const responses = ips.map(ip => new Promise((resolve, reject) => {
    const ws = new WebSocket(`ws://${ip}:80`);
    
    let timeout = setTimeout(() => {
      // Save the state before closing, otherwise it will always be the closed state.
      const currentState = ws.readyState;
      ws.close();
      reject({
        message: 'Socket connection timeout', 
        state: currentState
      });
    }, 5000);

    ws.onopen = () => {
      clearTimeout(timeout);
      resolve(ws);
    };

    ws.onerror = event => {
      clearTimeout(timeout);
      reject({
        message: 'Socket connection error',
        event
      });
    };
  }));

  const sockets = await Promise.all(responses);
  return sockets;
}
getip().then(sockets => {
  console.log('connected!', sockets);
}).catch(error => {
  console.log(error);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM