我一直在我的ReactJS项目中使用异步等待babel。我发现使用React setState很方便,我想更好地理解。请考虑以下代码:
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。不漂亮。但是在代码示例中,await知道在状态更新后,handleChange已经完成了...但我认为await只适用于promises并等待承诺在继续之前解决。在handleChange中没有承诺也没有解决方案......它如何知道该等待什么?
暗示似乎是setState是异步运行的,而await在某种程度上意识到它何时完成。也许setState在内部使用promises?
版本:
做出反应:" ^ 15.4.2"
babel-core:" ^ 6.26.0"
babel-preset-env:" ^ 1.6.0",
babel-preset-react:" ^ 6.24.1",
babel-preset-stage-0:" ^ 6.24.1"
babel-plugin-system-import-transformer:" ^ 3.1.0",
babel-plugin-transform-decorators-legacy:" ^ 1.3.4",
babel-plugin-transform-runtime:" ^ 6.23.0"
答案 0 :(得分:25)
this.handleChange ,在等待的右侧执行:
2.1。 setState 运行其更新程序,但由于 setState 无法保证立即更新,因此可能会将更新安排在稍后的时间 (它没有'无论是直接的还是以后的,重要的是它的预定时间
2.2。 console.log('同步代码')运行...
2.3。 this.handleChange 然后退出 undefined (返回undefined,因为函数返回undefined,除非另有明确说明)
await 然后接受 undefined ,因为它不是承诺,它使用 Promise.resolve将其转换为已解决的承诺(未定义)并等待它 - 它不能立即使用,因为它在幕后传递给 .then 方法是异步的:
“传递给promise的回调永远不会被调用 完成当前运行的JavaScript事件循环“
3.1。这意味着未定义将被置于事件队列的后面,(这意味着它现在位于事件队列中的setState更新程序之后...)
事件循环最终到达并获取我们的 setState 更新,现在执行...
事件循环到达并选择未定义,其评估为未定义 (如果我们需要,我们可以存储,因此=在等待存储已解决的结果之前常用的<)>
5.1。 Promise.resolve()现已完成,这意味着等待不再有效,因此该功能的其余部分可以恢复
答案 1 :(得分:4)
我还没有对此进行测试,但这是我认为正在发生的事情:
undefined
返回的await
在setState
回调后排队。 await
正在Promise.resolve
下面(regenerator-runtime
),这反过来会控制事件循环中的下一个项目。
因此,setState
回调恰好在await
之前排队,这是巧合。
您可以通过在setState
周围放置一个setTimeout(f =&gt; f,0)进行测试。
regenerator-runtime
中的 babel
本质上是一个使用Promise.resolve
来产生控制权的循环。您可以在_asyncToGenerator内看到它,Promise.resolve
。
答案 2 :(得分:1)
await的rv
或返回值定义为:
rv
Returns the fulfilled value of the promise, or the value itself if it's not a Promise.
因为handleChange不是异步或承诺值,它只是返回自然值(在这种情况下,没有返回,所以undefined
)。因此,这里没有异步事件循环触发器“让它知道handleChange已完成”,它只是按照你给它的顺序运行。
答案 3 :(得分:0)
setState()
并不总是立即更新组件doc
但可能就是这种情况。
如果您想使用承诺替换回调,您可以自己实现:
setStateAsync(state) {
return new Promise((resolve) => {
this.setState(state, resolve)
});
}
handleChange = (e) => {
return this.setStateAsync({[e.target.name]: e.target.value})
}
参考:https://medium.com/front-end-hacking/async-await-with-react-lifecycle-methods-802e7760d802