async await 与 setState 类似,在主线程执行的时候,遇到异步任务总是先挂载起来,一边执行一边等待主线程上的同步任务执行完毕,等同步任务执行完毕,再发送信号给挂载起来的任务,说你可以进主线程来执行了,此时挂载起来的异步任务中谁先执行完毕谁就先去主线程上执行
而两者不同的点在于:遇到 async await 的时候,会先返回(把任务挂载),等同步任务执行完毕,再根据挂载任务是否返回值决定是否去主线程执行,然而,async await 在挂载时,跟在其后的语句也会跟着停止执行,只有等 await 返回值,其后的语句才能执行;setState 在挂载时,并不影响其后语句的执行,也就是说当遇到 setState 时,会将 setState 挂载起来,转而去执行其后的同步语句,等 setState 执行完毕,那么再放入主线程执行。如下所示:
import React,{useState, useEffect} from 'react' import { withRouter } from 'umi'; import { connect } from 'dva'; import decode from 'jwt-decode'; import { Row, Col, Spin, } from 'antd' import Header from '@/containers/Header' import SideBar from '@/containers/SideBar' import DepRecMedicineContainer from '@/containers/DepRecMedicine' function Index (props) { //... const [tokenUserInfo, setTokenUserInfo] = useState([]) const [isReturn, setIsReturn] = useState(false) const verify = async ()=>{ const { dispatch } = props console.log('1') // 日志1 await dispatch({ type: 'GetData/getToken', callback: (data) => { setTokenUserInfo(data) console.log('2') // 日志2 if(data.status === '1'){ const token = localStorage.getItem('@#@TOKEN') const tk = decode(token) // console.log('token/index',token) if(token){ try{ dispatch({ type: 'GetData/saveData', payload: {token: tk} }) }catch{ // 报错 localStorage.removeItem("@#@TOKEN") window.location.href = '/login' } } }else{ localStorage.removeItem("@#@TOKEN") window.location.href = '/login' } } }) console.log('3') // 日志3 } useEffect(() => { verify() console.log('4') // 日志4 setIsReturn(true) console.log('5') // 日志5 },[]) // 指定空数组,只在组件挂载时(刷新)执行一次 const {location} = props console.log('是render内的isReturn',isReturn) // 打印isReturn if(isReturn == true && tokenUserInfo.status == '1'){ if(location.pathname === '/'){ return( <div style={{height:'100vh', overflow: 'hidden'}}> {/* header */} <Row> <Header /> </Row> {/* body */} <Row> <Col span={3}> <SideBar // onClickDepRec={onClickDepRec} // onClickAdmitPatientList={onClickAdmitPatientList} // onClickLeavePatientList={onClickLeavePatientList} // onClickToChangeRightContent={onClickToChangeRightContent} /> </Col> <DepRecMedicineContainer /> </Row> </div> ) }else{ return( <> {props.children} </> ) } }else{ return <Spin /> } } export default connect(({GetData})=>({GetData}))(withRouter(Index))