I have the following code, which ES Lint marks as a race condition:
const fillPersonPositions = async (person) => {
person.positions = await getPositions(person.id);
};
Full error:
Possible race condition:
person.positions
might be reassigned based on an outdated value ofperson.positions
.eslint(require-atomic-updates)
If I change person.id
to something unrelated to the person
object like null
, the error vanishes.
What is the problem here and how to avoid it? (I mean fix code if it's a real race condition problem or tell the linter that it's not a problem if not).
This code could be problematic if you called fillPersonPositions
more than once, and the id
of the person changed in the meantime. Eg:
person.id = 1;
const p1 = fillPersonPositions(person);
person.id = 3;
const p2 = fillPersonPositions(person);
await Promise.all([p1, p2]);
Here, there's no guarantee that the first fillPersonPositions
resolves first, so at the end, you might end up with person
having an ID of 3, but a positions
property corresponding to the ID of 1.
Of course, the above is very contrived, but ESLint does not know that.
One possible fix would be to avoid mutation, and instead return (and use) a new object:
const fillPersonPositions = async (person) => {
const positions = await getPositions(person.id);
return { ...person, positions };
};
(It's often a good idea to avoid mutation when possible anyway, for the sake of more understandable code - for similar reasons, const
is a better choice than let
when you have the option)