Javascript - 在Websocket上使用Promise?

Pie*_*iet 12 javascript websocket promise

我在纯Javascript中使用Websockets,我想在Websocket函数中实现Promises.我没有得到任何错误,但承诺不起作用.

使用以下代码,我可以成功连接到socketserver,但Promise似乎被跳过,因为警报的输出总是"失败".

有人知道这种情况下的问题是什么吗?Ps:我在最新的谷歌Chrome浏览器和最新的Mozilla Firefox浏览器中进行了测试,我省略了一些基本的检查/错误处理.

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');
    });
}
Run Code Online (Sandbox Code Playgroud)

jfr*_*d00 27

您尝试在新连接中使用promises似乎有点误导.您将希望返回一个承诺,connect()以便您可以使用它来了解服务器何时连接.

看起来你可能想要这样的东西:

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);
        };

    });
}
Run Code Online (Sandbox Code Playgroud)

然后,你会像这样使用它:

connect().then(function(server) {
    // server is ready here
}).catch(function(err) {
    // error here
});
Run Code Online (Sandbox Code Playgroud)

或者async/await像这样:

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

  • @Piet - 这根本不是承诺的工作方式.承诺是一次性设备.他们只开过一次.传入的消息可能不止一次发生,因此它们不是承诺的良好设计匹配.此外,每次发生新事件时,您都不会创建新的承诺.这不是承诺的工作方式.您在触发某些异步操作时创建一个promise,并且您正在等待该操作中的唯一一个响应.然后,承诺用于监控一个结果.您只需要使用常规回调来重复发生事件. (6认同)

Hyy*_*her 7

扩展@jfriend00 答案,因为他的答案每次connect调用该方法时都会尝试创建一个新连接,并且不考虑连接关闭的情况

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);
    };
  });
}
Run Code Online (Sandbox Code Playgroud)

并使用它

getSocket().then(function(server) {
  // do stuff
}).catch(function(err) {
    // error here
});
Run Code Online (Sandbox Code Playgroud)

或使用异步/等待

const socket = await getSocket();
Run Code Online (Sandbox Code Playgroud)


vit*_*ets 5

我面临着完全相同的问题,并创建了一个小型的websocket-promise库。它返回连接/断开连接和发送消息的承诺:

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.'));
Run Code Online (Sandbox Code Playgroud)

关于消息,有两种选择:

  1. 如果您发送数据并期望响应消息-您可以通过以下.sendRequest()方法使用Promise :

    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'}
    
    Run Code Online (Sandbox Code Playgroud)
  2. 如果您只想发送消息而不希望得到响应,请使用.send()方法:

    wsp.send(data); // returns undefined
    
    Run Code Online (Sandbox Code Playgroud)