等待异步 - Eslint Require-ratomic-tostes中的种族条件错误



与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-ratomic-updates

您可以安全地忽略警告:(

Eslint旨在捕捉这样的东西:

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

在这种情况下,race在堆栈上记忆valueawait s tick,然后写回value。随着其他代码在此期间运行,可以更改value,然后更新可能关闭...它不是原子。

在您的情况下,您从ctx.request.body阅读并写入ctx.body,因此没有非原子更新。另外,可能没有其他中间件同时吸引相同的ctx,因此不能进行任何并发修改。因此,在您的情况下,这是一个假阳性,甚至可以以任何方式肯定(可能是Eslint中的一个错误(。

我意识到这个答案对此答案有点迟了,但是仅对任何未来的用户遇到此问题,在.eslintrc.json或您使用的任何相关配置中禁用此规则,只需指定:

"require-atomic-updates": "off"

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

只要ctx变量在doRequest之外定义,ctx.body分配就处于竞赛状态。因为不可能确保分配给ctx.body的最后一个值属于doRequest的最后一个呼叫。

我写了一篇有关这种种族条件的博客文章。有两种避免此警告的方法

方法1:将ctx移至doRequest主体,然后在功能末端返回ctx值。

方法2:使用Promote-Base-semaphore模式

let ctxPromise

每当您启动请求时,请致电ctxPromise = doRequest()

相关内容

  • 没有找到相关文章

最新更新