1

In the non-blocking event loop of JavaScript, is it safe to read and then alter a variable? What happens if two processes want to change a variable nearly at the same time?

Example A:

  • Process 1: Get variable A (it is 100)
  • Process 2: Get variable A (it is 100)
  • Process 1: Add 1 (it is 101)
  • Process 2: Add 1 (it is 101)
  • Result: Variable A is 101 instead of 102

Here is a simplified example, having an Express route. Lets say the route gets called 1000 per second:

let counter = 0;

const getCounter = () => {
  return counter;
};

const setCounter = (newValue) => {
  counter = newValue;
};

app.get('/counter', (req, res) => {
  const currentValue = getCounter();
  const newValue     = currentValue + 1;
  setCounter(newValue);
});

Example B:

What if we do something more complex like Array.findIndex() and then Array.splice()? Could it be that the found index has become outdated because another event-process already altered the array?

  • Process A findIndex (it is 12000)
  • Process B findIndex (it is 34000)
  • Process A splice index 12000
  • Process B splice index 34000
  • Result: Process B removed the wrong index, should have removed 33999 instead
const veryLargeArray = [
  // ...
];

app.get('/remove', (req, res) => {
  const id = req.query.id;
  const i  = veryLargeArray.findIndex(val => val.id === id);
  veryLargeArray.splice(i, 1);
});

Example C:

What if we add an async operation into Example B?

const veryLargeArray = [
  // ...
];

app.get('/remove', (req, res) => {
  const id = req.query.id;
  const i  = veryLargeArray.findIndex(val => val.id === id);

  someAsyncFunction().then(() => {
    veryLargeArray.splice(i, 1);
  });
});

This question was kind of hard to find the right words to describe it. Please feel free to update the title.

10
  • 1
    things like Array.findIndex() or Array.map() arent async, they are sync Commented Apr 2, 2020 at 12:02
  • But app.get() is? Commented Apr 2, 2020 at 12:03
  • all the example you have given is using global var. of in-memory data. You should not do this anywhere. It Is not even recommended. Commented Apr 2, 2020 at 12:04
  • @xdeepakv this is just an example to abstract the problem Commented Apr 2, 2020 at 12:04
  • 1
    This documentation gives an overview of the Javascript concurrency model: developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop Commented Apr 2, 2020 at 18:34

1 Answer 1

1

As per @ThisIsNoZaku's link, Javascript has a 'Run To Completion' principle:

Each message is processed completely before any other message is processed.

This offers some nice properties when reasoning about your program, including the fact that whenever a function runs, it cannot be pre-empted and will run entirely before any other code runs (and can modify data the function manipulates). This differs from C, for instance, where if a function runs in a thread, it may be stopped at any point by the runtime system to run some other code in another thread.

A downside of this model is that if a message takes too long to complete, the web application is unable to process user interactions like click or scroll. The browser mitigates this with the "a script is taking too long to run" dialog. A good practice to follow is to make message processing short and if possible cut down one message into several messages.

Further reading: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

So, for:

Example A: This works perfectly fine as a sitecounter.

Example B: This works perfectly fine as well, but if many requests happen at the same time then the last request submitted will be waiting quite some time.

Example C: If another call to \remove is sent before someAsyncFunction finishes, then it is entirely possible that your array will be invalid. The way to resolve this would be to move the index finding into the .then clause of the async function.

IMO, at the cost of latency, this solves a lot of potentially painful concurrency problems. If you must optimise the speed of your requests, then my advice would be to look into different architectures (additional caching, etc).

Sign up to request clarification or add additional context in comments.

2 Comments

If it is like that, example C should not work does it?
My bad, yes, it is not guaranteed that example C will work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.