Alex
Alex

Reputation: 68016

Promisify event based pattern

How can I promisify a websocket event based communication, to work like ajax?

constructor(){
  this.ws = new WebSocket(...);
  this.ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    // send data to doRequest
  };

},

async function doRequest(data){
  this.ws.send(JSON.stringify(data));
  return new Promise((resolve, reject) => {
    // how to wait and get data?
    resolve(data);
  });
}

I was thinking to add my own event emmiter and fire event inside onmessage function, then hook the promise from doRequest to that event, but seems kind of convoluted?

Upvotes: 1

Views: 355

Answers (1)

Emiel Zuurbier
Emiel Zuurbier

Reputation: 20944

Websockets can receive and send data in both directions at any time, whereas Promises only resolve once with one value. Thus Promises might not be the right tool here.

If you however want to write an abstraction around the response to one request, then a Promise makes perfectly sense:

Add an event listener that listens for the message event, but only listen for it once and remove it, send the data and resolve whenever the message event has been dispatched.

Remove function as this is a method of the class you are creating.

doRequest(data){
  return new Promise(resolve => {
    this.ws.addEventListener('message', event => {
      resolve(event.data);
    }, {once: true});
    this.ws.send(JSON.stringify(data));    
  });
}

In your constructor only create the WebSocket instance.

constructor(){
  this.ws = new WebSocket(...);
}

And then use it like this:

const socket = new YourWebSocketClass();
socket.doRequest({message: 'hello'}).then(message => {
  const data = JSON.parse(message);
});

Upvotes: 2

Related Questions