william_dev
william_dev

Reputation: 39

nodejs concurrency synchronous execution

I've two WebSockets getting data asynchronously, every time I get some message from the sockets I execute some code in CompareData.

The problem is that CompareData should be executed synchronously, or (better) only if it is not already running

This is my code:

function CompareData(data) {
    console.log('data ', data);
    AsyncFunction();
};
ws1 = new WebSocket(WS1_URL);
ws2 = new WebSocket(WS2_URL);
ws1.on('message', (data) => {
    CompareData(data);
});
ws2.on('message', (data) => {
    CompareData(data);
});

Can you help me, please? I'm very new to NodeJs

Upvotes: 1

Views: 704

Answers (4)

jedzej
jedzej

Reputation: 444

My suggestions are:

  1. First of all, you need to know when CompareData is finished. Reorganize your code to use promises or callbacks. If you're using third-party async functions, I'm almost sure they provide some feedback on completion - This is a must have in async world
  2. Add inProgress = false flag somewhere to serve for you as simple lock. As someone posted, JS is single-threaded and you're guaranteed that your code won't get interrupted in the middle of operation. Thanks to that you can use really simple locks instead of complicated os-based mutexes known from multithreaded langs.
  3. In ws.on(...) check if inProgress is set. If not, lock it and run CompareData
  4. In CompareData completion callback or on promise resolution set inProgress back to false, so you're no longer ignoring incoming data.

If you can simply discard the data, there is no need to complicate this scenario with extra queues, mutexes, etc.

If you need to serve it all, then queue incoming data and serve next piece after completion callback is fired.

This is basically what Rahul's suggests, but he uses features that are not established in current version of standard, so don't use it if you're not transpiling your code.

Upvotes: 0

oniramarf
oniramarf

Reputation: 903

You should use some mutex in order to avoid that two async operations of compareData are executed at the same time, like node-mutex or mutexify.

Upvotes: 0

Rahul Sharma
Rahul Sharma

Reputation: 10081

You should not make synchronous call in node.js but you can make those call sequential. See below example might be helpful.

var messages = [];
var inProgress = false;

function CompareData(data) {
  return new Promise((resolve, reject) => {
    // do some stuff and resolve
    setTimeout(() => {
      resolve(data);
    }, 1000);
  });
};

const start = async () => {
  if (!inProgress) {
    if (messages.length !== 0) {
      inProgress = true;
      try {
        const data = await CompareData(messages.shift());
        console.log(data);
      } catch (error) {
        console.log(error);
      }
      inProgress = false;
      await start();
    }else{
      console.log('Process Done');
    }
  }
}

const handler = (data) => {
  messages.push(data);
  start();
}

handler(1);
handler(2);
handler(3);
handler(4);

// ws1 = new WebSocket(WS1_URL);
// ws2 = new WebSocket(WS2_URL);
// ws1.on('message', handler);
// ws2.on('message', handler);

Upvotes: 0

selbie
selbie

Reputation: 104569

Node.js is single threaded. So you don't really get true concurrency issues occurring in Node programs as you might in other languages. In your example, there can only be at most one WebSocket callback for CompareData occurring at any given time.

Upvotes: 2

Related Questions