使用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
答案 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
在堆栈上存储value
,await
滴答,然后写回到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()
。