此 Async Await 不应该工作。为什么它会起作用?

This Async Await should not be working. Why is it working then?

所以我已经 React-Native 几个月了,我偶然发现了一种情况,其中必须在 setState 函数中更新一个巨大的块。之后我不得不调用一个依赖于该状态的函数。 当然状态并没有立即发生变异,因为我知道setState是异步的。

这是我的结构

Parent

stateSetter = (data) => {
        this.setState({
            ...data
        })
    }
dateFilter = () => {
        let startDate = this.state.startDate
        let endDate = this.state.endDate
        if (startDate !== "" && endDate == "") {
            this.setState({
                DataFiltered: this.state.Data.filter(elem => Helper.convertDateToISO(elem.date)>= Helper.convertDateToISO(startDate))
            })
        }else if(startDate == "" && endDate !== ""){
            this.setState({
                DataFiltered: this.state.Data.filter(elem => Helper.convertDateToISO(elem.date)<= Helper.convertDateToISO(endDate))
            })
        }else if(startDate !== "" && endDate !== ""){
            this.setState({
                DataFiltered: this.state.Data.filter(elem => Helper.convertDateToISO(elem.date)>= Helper.convertDateToISO(startDate) && Helper.convertDateToISO(elem.date)<= Helper.convertDateToISO(endDate))
            })
        }else if(startDate === "" && endDate === ""){
            this.setState({
                DataFiltered: this.state.Data
            })
        }
    }

Child

<TouchableWithoutFeedback onPress={async () => {
                await stateSetter({
                    ["startDate"]: "",
                    ["endDate"]: "",
                    ["startDateText"]: "From...",
                    ["endDateText"]: "To..."
                })
                dateFilter()
            }} >

现在我相信 Async Await 在 await 等待 promise 时工作......对吗? 所以按照这个逻辑,在上述代码中,await 和 async 应该对程序没有影响。

相反

当我不使用 async await 时,它不起作用。它仅在我使用 async await 时有效。

当我刚开始学习异步时,我尝试了一些东西并且 none 成功了。

this.setState({ ...data }, () => {
  this.dateFilter()
})
//Had no effect

另外:Promise 无效。

TlDr:为什么我的异步等待工作正常?

  1. await 因为 stateSetter 没有 return 承诺
  2. ,所以您的示例将无法按预期工作

要使 await 适用于 stateSetter,它必须 return 一个 Promise

stateSetter = (data) => {
   return new Promise(resolve => setTimeout(resolve, 3000));
}
  1. 检查这个非常好关于这里发生的事情

tl;dr:因为您正在使用 await,函数的其余部分计划在将来执行,并且在那个时间点状态将被更新。你是否真的 await 承诺是无关紧要的。


我不知道 React 的内部结构,但我假设队列 micro task 来更新状态。 Promise 回调也作为微任务处理(async/await 是处理 promises 的好方法)。

所以首先React添加了一个更新状态的微任务,然后await添加了一个恢复功能的微任务。

我们实际上可以做一个简单的实验来验证事件的顺序,方法是将回调传递给 setState(没有 JSX,因为不知何故我无法使其成为一个工作片段):

class Component extends React.Component {
  async doStuff() {
    await this.setState({newState: true}, () => console.log('inside setState callback', JSON.stringify(this.state)));
    console.log('after await this.setState', JSON.stringify(this.state));
  }
  
  render() {
    return React.createElement('button', {onClick: () => this.doStuff()}, 'Click me');
  }
}

ReactDOM.render(
  React.createElement(Component),
  document.body
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

如果您 运行 这样做,您会看到首先调用回调。我们知道此时状态已经更新,因为这就是回调的全部目的:它在状态更新时执行。

然后执行函数的其余部分,由于状态已经更新,它将访问新状态。

但是,由于您自己想知道为什么这样做有效,我建议您不要采用这种做法,而只使用 setState 回调。