How to implement Command Pattern with async/await in JS

291 Views Asked by At

I'm currently implementing a WebSocket connection and I'm using a command pattern approach to emit some messages according to the command that users execute.

This is an abstraction of my implementation:

let socketInstance;
const globalName = 'ws'
const globalObject = window[globalName];
const commandsQueue = isArray(globalObject.q) ? globalObject.q : [];
globalObject.q = {
  push: executeCommand
};

commandsQueue.forEach(command => {
  executeCommand(command);
});

function executeCommand(params) {
  const actions = {
    create,
    send
  };
  const [command, ...arg] = params;

  if (actions[command]) {
    actions[command](arg);
  }
}

function send([message]) {
  socketInstance.send(message);
}

function create([url]) {
  socketInstance = new WebSocket(url);
}

In order to start sending messages, the user should be run:

window.ws.push('create', 'ws://url:port');
window.ws.push('send', 'This is a message');

The problem that I have is the connection is async, and I need to wait until the connection is done to continue to the next command. Is it a good idea to implement an async/await in commandsQueue.forEach or an iterator is a better approach? What other best approaches do you recommend?

1

There are 1 best solutions below

0
On

The solution that I'm using right now is: I created an empty array of messages at the beginning and then every time that I call the send command I verify if the connection wasn't opened and I added to this array.

Something like that:

const messages = [];
let socketInstance;
let isConnectionOpen = false;
const globalName = "ws";
const globalObject = window[globalName];
const commandsQueue = isArray(globalObject.q) ? globalObject.q : [];
globalObject.q = {
  push: executeCommand,
};

commandsQueue.forEach((command) => {
  executeCommand(command);
});

function executeCommand(params) {
  const actions = {
    create,
    send,
  };
  const [command, ...arg] = params;

  if (actions[command]) {
    actions[command](arg);
  }
}

function send([message]) {
  if (isConnectionOpen) {
    socketInstance.send(message);
  } else {
    messages.push(message);
  }
}

function onOpen() {
  isConnectionOpen = true;
  messages.forEach((m) => {
    send([m]);
  });
  messages.length = 0;
}

function create([url]) {
  socketInstance = new WebSocket(url);
  socketInstance.onopen = onOpen;
}