反应重定向asyc并等待不等待

时间:2019-01-12 19:50:04

标签: reactjs promise async-await

我有以下代码,我想从url中获取访问令牌并将其放入会话存储,并让我的子组件使用该访问令牌来获取我的信息。但是,第一次加载组件时,似乎找不到访问令牌,但是如果我再次刷新它,则可以使用。为了解决此问题,我想到了使用async / await,以便在未设置会话令牌之前不会进一步重定向到子组件,但这似乎并不等待令牌被设置。不知道我在做什么错吗?

class App extends React.Component {
constructor(props){
    super(props);
    this.processToken();
}

componentDidMount() {
   const { user } = this.props; 
   const { accessToken } = user;
   // expecting access token to print here by it is not
   console.log('user token : ', accessToken);
}
 processToken = async () => {
try {
    const params = querySearch(this.props.location.search);
    if('accessToken' in params){
       await new Promise((resolve,reject) => {
          this.setOrderContext(params);
           resolve();
       } );  
        this.props.history.push(`/myinfo`);
    }
} catch(ex) {
  console.log(ex);
}

}

   setOrderContext (params){
     //this action calls a reducer and put the token in session storage
     this.props.userActions.processUserToken({data: {accessToken:params.accessToken}});

}

render() {
    return (

        <Switch>
            //myinfo component needs accessToken to retrieve my info
            <Route path="/myInfo" component={InofUI.App} />
        </Switch>

    );
}

2 个答案:

答案 0 :(得分:0)

问题出在构造函数内部的this.processToken()调用中。由于您不需要也不可以等待此调用,因此React只需调用该方法并继续其生命周期。 因此,可能是在您componentDidMount完成之前调用了setOrderContext

与往常一样,在React环境中,您应该获取资源并在componentDidMount内进行异步调用。这样可以确保您的组件在访问任何外部资源之前都能呈现平滑且正确的状态。

您要做的是将this.processToken()调用从构造方法移至componentDidMount方法,并确保在那里正确处理了该方法。

答案 1 :(得分:0)

这对我有用。

class App extends React.Component {

componentDidMount() {
   this.processToken();

}
 processToken = () => {
    try {
        const params = querySearch(this.props.location.search);
        if('accessToken' in params){
            this.setOrderContext(params);
            this.props.history.push(`/myinfo`);
        }
    } catch(ex) {
      console.log(ex);
    }
    }

   setOrderContext (params){
     //this action calls a reducer and put the token in session storage
     this.props.userActions.processUserToken({data: {accessToken:params.accessToken}});
}

render() {
    return (

        <Switch>
            //myinfo component needs accessToken to retrieve my info
            <Route path="/myInfo" component={InofUI.App} />
        </Switch>

    );
} 

然后在InfoUI.App内部

componentDidMount() {
        this.retrieveMyInfo();
    }

    retrieveMyInfo = async () => {
        await this.untilTokenIsSet();
        const { location, history } = this.props;
        this.props.processUser(location, history);
    }

    untilTokenIsSet= () => {
        const poll = (resolve) => {
            const { user } = this.props;
            const { accessToken } = user;
            console.log('getting accessToken', accessToken);
            if (accessToken) {
                resolve();
            } else {
                console.log('wating for token .. ');
                setTimeout(() => poll(resolve), 100);
            }
        };
        return new Promise(poll);
    }