Reactjs 为什么Async Wait与React setState一起工作?
在我的ReactJS项目中,我一直在使用AsyncWait和babel。我发现React setState有一个方便的用法,我只是想更好地理解它。考虑这个代码:Reactjs 为什么Async Wait与React setState一起工作?,reactjs,async-await,babeljs,Reactjs,Async Await,Babeljs,在我的ReactJS项目中,我一直在使用AsyncWait和babel。我发现React setState有一个方便的用法,我只是想更好地理解它。考虑这个代码: handleChange = (e) => { this.setState({[e.target.name]: e.target.value}) console.log('synchronous code') } changeAndValidate = async (e) => { await this.han
handleChange = (e) => {
this.setState({[e.target.name]: e.target.value})
console.log('synchronous code')
}
changeAndValidate = async (e) => {
await this.handleChange(e)
console.log('asynchronous validation code')
}
componentDidUpdate() {
console.log('updated component')
}
我的意图是在组件更新后运行异步验证代码。而且它有效!生成的控制台日志显示:
synchronous code
updated component
asynchronous validation code
验证代码仅在handleChange更新状态并呈现新状态后运行
通常,要在状态更新后运行代码,必须在this.setState之后使用回调。这意味着如果您想在handleChange之后运行任何东西,您必须给它一个回调参数,然后将该参数传递给setState。不漂亮。但在代码示例中,Wait知道在状态更新后handleChange已完成。。。但我认为等待只适用于承诺,并在继续之前等待承诺解决。没有承诺,也没有决心改变。。。它怎么知道等待什么
这似乎意味着setState是异步运行的,而wait在某种程度上知道它何时完成。也许setState在内部使用承诺
版本:
反应:“^15.4.2”
巴别塔核心:“^6.26.0”
巴别塔预设环境:“^1.6.0”
巴别塔预设反应:“^6.24.1”
巴别塔-preset-stage-0:“^6.24.1”
babel插件系统导入转换器“^3.1.0”
babel插件转换装饰程序传统:“^1.3.4”
babel插件转换运行时:“^6.23.0”等待的
rv
或返回值定义为:
rv
Returns the fulfilled value of the promise, or the value itself if it's not a Promise.
因此,由于handleChange不是异步或承诺值,它只是返回自然值(在本例中,没有返回,因此未定义)。因此,这里没有异步事件循环触发器“让它知道handleChange已经完成”,它只是按照您给定的顺序运行
setState()
并不总是立即更新组件
但这里可能是这样
如果您想用承诺替换回调,您可以自己实现它:
setStateAsync(state) {
return new Promise((resolve) => {
this.setState(state, resolve)
});
}
handleChange = (e) => {
return this.setStateAsync({[e.target.name]: e.target.value})
}
ref:我还没有测试过,但我认为这是正在发生的事情:
wait
返回的undefined
在setState
回调后排队。await
正在执行下面的Promise.resolve
(在再生器运行时
中),这反过来会产生对事件循环上下一项的控制
因此,setState
回调恰好在wait
之前排队,这是巧合
您可以通过在setState
周围放置一个setTimeout(f=>f,0)来测试这一点
babel
中的再生器运行时
本质上是一个使用Promise.resolve
来产生控制的循环。你可以看到的内部,它有一个承诺。解决
我尽力简化和补充Davin的答案,这样你就可以更好地了解这里到底发生了什么:
wait放在前面。handleChange,这将安排其余更改和验证功能的执行,仅在wait解析其右侧指定的值时运行,在这种情况下,this.handleChange返回的值
此.handleChange位于wait右侧,执行:
2.1setState运行其更新程序,但由于setState不能保证立即更新,因此它可能会将更新安排在稍后的时间(无论是立即更新还是在稍后的时间点更新,重要的是它的计划时间)
2.2。console.log(“同步代码”)正在运行
2.3this.handleChange然后退出,返回undefined(返回undefined,因为除非另有明确指定,否则函数返回undefined)
等待然后接受这个未定义的,因为它不是承诺,所以使用承诺将其转换为已解决的承诺。解决(未定义)并等待它-它不是立即可用的,因为在幕后它被传递到它的。然后是异步的方法:
“传递到承诺中的回调将永远不会在
“JavaScript事件循环当前运行的完成”
3.1。这意味着未定义的将被放入事件队列的后面(这意味着它现在位于事件队列中的setState更新程序后面…)
事件循环最终到达并获取我们的设置状态更新,该更新现在执行
事件循环到达并拾取未定义的,该循环的计算结果为未定义的(如果需要,我们可以存储该循环,因此在等待存储解析结果之前常用的=值)
5.1Promise.resolve()现在完成,这意味着wait不再生效,因此函数的其余部分可以恢复
您的验证代码将运行
上面的代码在undefined
上有一个wait
(因为handleChange
不返回任何内容)。你确定它对设置状态有影响吗?你使用的是什么版本的React和babel?这很奇怪,但我确认等待生效<代码>等待这个.setState({data:true},()=>console.log('callback');log('inline')
明确表示将首先触发回调
,但是-remove wait并按照通常设置的方式工作-假设工作-内联
,然后回调
@davintroon似乎正确