等待异步-ESLint中的竞态条件错误require-atomic-updates

时间:2019-07-04 18:37:26

标签: javascript async-await eslint race-condition

使用ESLint检查时,以下代码会导致竞争状态:

  let match = false

  try {
    match = await something()
  } catch (err) {
    // do something
  }
  if (match === false) {
    // do something
  }

编写此代码块的更好方法是什么?

编辑:

  let request = ctx.request.body || {}
  let password = request.password
  let match = false

  try {
    match = await bcrypt.compare(password, 'xxxxx')
  } catch (err) {
    ctx.throw(401, err)
  }
  if (match === false) {
    ctx.throw(401, 'invalid password')
  }

  ctx.body = {
    message: 'logged in ok'
  }

ESLint错误:

  

可能的竞争条件:ctx.body可能会根据   ctx.body的过期值require-atomic-updates

3 个答案:

答案 0 :(得分:2)

我知道这个答案有点迟了,但是对于以后遇到此问题的任何用户,要在您的.eslintrc.json或您使用的任何相关配置中禁用此规则,只需指定:

"require-atomic-updates": "off"

答案 1 :(得分:1)

您可以放心地忽略警告:)

ESLint旨在捕捉这样的事情:

  let value = 0;

  async function race() {
    value += await Promise.resolve(1);
    console.log(value);
  }

 race(); race();

在这种情况下,race在堆栈上存储valueawait滴答,然后写回到value。当其他代码同时运行时,value可能已经更改,然后更新可能已关闭……这不是原子的。

但是,对于您而言,您是从ctx.request.body读取并写入ctx.body的,所以没有非原子更新。另外,可能没有其他中间件同时使用相同的ctx,因此不能进行任何并行修改。因此,在您的情况下,这是一个误报,甚至以任何方式肯定都值得怀疑(这可能是ESLint中的错误)。

答案 2 :(得分:0)

我不认为这是一个错误。假设您的代码段包含在异步函数doRequest中。

只要在ctx外部定义了doRequest变量,ctx.body分配就处于竞争状态。因为无法确保分配给ctx.body的最后一个值属于doRequest的最后一次调用。

我写了an blog post关于这种比赛条件的信息。有两种方法可以避免出现此警告

方法1:将ctx移到doRequest正文中,然后在函数末尾返回ctx值。

方法2:使用promise-base-semaphore pattern

let ctxPromise

每当您发出请求时,都要拨打电话ctxPromise = doRequest()