Javascript - Using Promises on Websocket?

2019-02-17 12:44发布

问题:

I am using Websockets in pure Javascript and I want to implement Promises into the Websocket functions. I don't get any errors but the Promise doesn't work.

Using the following code I can connect succesful to the socketserver but the Promise seems to be skipped because the output of the alert is always "failed".

Does somebody knows what the problem is in this case? Ps: I did the tests in the latest Google Chrome browser and the latest Mozilla Firefox browser, and I left out some basic checking/error handling for this example.

function Connect()
{
    server = new WebSocket('mysite:1234');

    server.onopen = (function()
    {
        return new Promise(function(resolve, reject) 
        {
            if (true)
            {
                resolve();
            }
            else
            {
                reject();
            }
        });
    }).then = (function()
    {
        alert('succeeed');
    }).catch = (function()
    {
        alert('failed');
    });
}

回答1:

Your attempt to use promises with the new connection seems a bit misguided. You will want to return a promise from connect() so you can use it to know when the server is connected.

It seems like you probably want something like this:

function connect() {
    return new Promise(function(resolve, reject) {
        var server = new WebSocket('ws://mysite:1234');
        server.onopen = function() {
            resolve(server);
        };
        server.onerror = function(err) {
            reject(err);
        };

    });
}

Then, you would use it like this:

connect().then(function(server) {
    // server is ready here
}).catch(function(err) {
    // error here
});

or with async/await like this:

async myMethod() {
  try {
      let server = await connect()
      // ... use server
  } catch (error) {
      console.log("ooops ", error)
  }
}


回答2:

I faced exactly the same problem and created tiny websocket-as-promised library. It returns promises for connecting / disconnecting and sending messages:

const WebSocketAsPromised = require('websocket-as-promised');
const wsp = new WebSocketAsPromised();

// connect
wsp.open('ws://echo.websocket.org')
  .then(() => console.log('Connected.')) 
  // send data and expect response message from server
  .then(() => wsp.sendRequest({foo: 'bar'}))
  .then(response => console.log('Response message received', response))
  // disconnect
  .then(() => wsp.close())
  .then(() => console.log('Disconnected.'));

Concerning messages there are two options:

  1. if you send data and expect response message - you can use promise via .sendRequest() method:

    wsp.sendRequest({foo: 'bar'}); // returns promise
    // actually sends message with unique id: {id: 'xxxxx', foo: 'bar'}
    // promise waits response message with the same id: {id: 'xxxxx', response: 'ok'}
    
  2. if you just want to send message and do not expect response - use .send() method:

    wsp.send(data); // returns undefined
    


回答3:

To extend @jfriend00 answer, as his answer tries to create a new connection every time the connect method is called and it does not consider the case where the connection is closed

function getSocket() {

  if (getSocket.server && getSocket.server.readyState < 2) {
    console.log("reusing the socket connection [state = " + getSocket.server.readyState + "]: " + getSocket.server.url);
    return Promise.resolve(getSocket.server);
  }

  return new Promise(function (resolve, reject) {

    getSocket.server = new WebSocket(SOCKET_URL);

    getSocket.server.onopen = function () {
      console.log("socket connection is opened [state = " + getSocket.server.readyState + "]: " + getSocket.server.url);
      resolve(getSocket.server);
    };

    getSocket.server.onerror = function (err) {
      console.error("socket connection error : ", err);
      reject(err);
    };
  });
}

and to use it

getSocket().then(function(server) {
  // do stuff
}).catch(function(err) {
    // error here
});

or with async/await

const socket = await getSocket();