Aero Wang
Aero Wang

Reputation: 9217

Why does boolean assignment after await triggers atomic update error?

let searching = false;

const search = async () => {
  if (searching) {
    throw new Error('No parallel process allowed.');
  }
  try {
    searching = true;
    const result = await someAsyncMethod();
    searching = false;
    return result;
  } catch (e) {
    searching = false;
    throw e;
  }
};

The above code will generate an atomic updates error in vscode saying "Possible race condition: searching might be reassigned based on an outdated value of searching" on the line 10 searching = false.

Why? Does it actually create data race?

Upvotes: 0

Views: 111

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370789

ESLint isn't smart enough to recognize the significance of the searching variable. The conditions for the rule violation are:

  • A variable or property is reassigned to a new value which is based on its old value.
  • A yield or await expression interrupts the assignment after the old value is read, and before the new value is set.
  • The rule cannot easily verify that the assignment is safe (e.g. if an assigned variable is local and would not be readable from anywhere else while the function is paused).

The logic ESLint sees is something like: "If searching is false when the function is called, reassign searching after an asynchronous method." It's warning that something else might have reassigned searching to true after the function was called, but before the await resolved, in which case reassigning after the await will be doing something based on the outdated value, which may not be desirable.

The following code without searching = true throws the same warning:

let searching = false;

const search = async () => {
  if (searching) {
    throw new Error('No parallel process allowed.');
  }
  try {
    const result = await someAsyncMethod();
    searching = false;
    return result;
  } catch (e) {
    searching = false;
    throw e;
  }
};

Despite your logic being sound, ESLint can't determine your exact intent. Feel free to disable the rule here.

Upvotes: 1

Related Questions