Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript承诺等待结果_Javascript_Reactjs_Promise - Fatal编程技术网

Javascript承诺等待结果

Javascript承诺等待结果,javascript,reactjs,promise,Javascript,Reactjs,Promise,我正在开发一个React应用程序,它将通过ADAL与Azure Ad进行身份验证。一切正常,但我需要在应用程序开始时加载JWT令牌。我想我将把我的两个函数包装起来,这两个函数在承诺中返回一个令牌,然后有条件地呈现它,但是出于某种原因,它不会“等待”我的承诺得到解决 欢迎任何帮助。干杯 import React, { Component } from 'react'; import { library } from '@fortawesome/fontawesome-svg-core'; imp

我正在开发一个React应用程序,它将通过ADAL与Azure Ad进行身份验证。一切正常,但我需要在应用程序开始时加载JWT令牌。我想我将把我的两个函数包装起来,这两个函数在承诺中返回一个令牌,然后有条件地呈现它,但是出于某种原因,它不会“等待”我的承诺得到解决

欢迎任何帮助。干杯

import React, { Component } from 'react';

import { library } from '@fortawesome/fontawesome-svg-core';
import { faIgloo, faBars } from '@fortawesome/free-solid-svg-icons';
import { initializeIcons } from '@uifabric/icons';
import { acquireToken, acquireGraphToken } from '../../adalConfig'

import Navbar from '../../common/navbar/navbar';
import Searchbar from '../../common/utils/searchBar/searchBar';
import LeftNavigation from '../../common/leftNavigation/leftNavigation';
import PageContainer from '../pageContainer/pageContainer';
import { IntlProvider } from 'react-intl';

import messages_en from '../../assets/translations/translations_en';
import messages_nl from '../../assets/translations/translations_nl';
import StylesheetLoader from '../../common/utils/stylesheetLoader/stylesheetLoader';
import ReactAI from 'react-appinsights';
import { connect } from 'react-redux';
import * as userActions from '../../store/users/actions';

initializeIcons();
library.add(faIgloo, faBars);

class App extends Component {

  state = {
    languageChoice: 'en',
    theme: 'red',
    tokensAreLoaded: false
  }

  componentWillMount() {

    let promise = new Promise((resolve, reject) => {
      const token = acquireToken();
      const graphToken = acquireGraphToken();

      if (token != '' && graphToken != '') {
        resolve(true);
      } else {
        reject(Error('promise failed'))
      }
    });

    promise.then( (value) => {
      this.setState({tokensAreLoaded: value});
    }, function (error){
      console.log('error getting promise value');
    })
  }

  componentDidMount() {
    this.props.onFetchCurrentUser();
  }    

  render() {

    if (this.state.tokensAreLoaded) {
      console.log('renderApp');
    } else {
      console.log('loading');
    }

    // Sets an interval that refreshes to get the token every 15 minutes
    // We use this because our custom API's do not automatically issue a
    // refresh token.
    setInterval(AppTokenRefresher, 900000);

    function AppTokenRefresher() {
      acquireToken();
      acquireGraphToken();
    } 

    const messages = {
        'nl': messages_nl,
        'en': messages_en
    };

    ReactAI.setAppContext({urlReferrer: document.referrer});
    // const Ai = ReactAI.ai();

    // function test() {
    //   Ai.trackEvent('Testing', { 'user': 'me' });
    // }

    const user = this.props.currentUser ? this.props.currentUser.name : 'test';

    return (
      <React.Fragment>
        <StylesheetLoader />
        {user}
        <IntlProvider locale={this.state.languageChoice} messages={messages[this.state.languageChoice]}>
          <div className="siteContainer">
            <Navbar currentUserProfile={this.props.currentUser}></Navbar>

            <div className="mobile-searchbar">
              <Searchbar />
            </div>

            <div className='page-container'>
              <aside>
                <LeftNavigation />
              </aside>

              <section className="main">
                <PageContainer />
            </section>

            </div>

          </div>
        </IntlProvider>

      </React.Fragment>
    );
  }
}

const mapStateToProps = state => {
  return {
      currentUserError: state.currentUserSlice.currentUserError,
      currentUserLoading: state.currentUserSlice.currentUserLoading,
      currentUser: state.currentUserSlice.currentUser,
      currentUserPicture: state.currentUserSlice.currentUserPicture
  }
}

const mapDispatchToProps= (dispatch) => {
  return {
      onFetchCurrentUser: () => dispatch(userActions.fetchCurrentUser()),
      onFetchCurrentUserPicture: () => dispatch(userActions.fetchCurrentUserPicture())
  }    
}

export default connect(mapStateToProps, mapDispatchToProps)(App);

看起来,
AuthenticationContext#acquireToken
是一种异步方法,它具有一个回调,在获取令牌时(或尝试这样做失败时)调用该回调

考虑重新定义包含对
acquireToken()
的调用的adal帮助器方法,使其成为
异步的
,或者在调用传递给
AuthenticationContext#acquireToken()
的回调时返回一个
Promise

export const acquireGraphToken = () => {  

    /* Return promise as acquireToken() is async */
    return (new Promise(resolve => {
        authContext.acquireToken(adalConfig.endpoints.graphApi, (message, token, msg) => {
                console.log('graph token', token);

                /* Resolve enclosing promise with token */
                resolve(token); 
            })
        }));    
} 

export const acquireToken = () => {  

    /* Return promise as acquireToken() is async */
    return (new Promise(resolve => {
        authContext.acquireToken(adalConfig.endpoints.oneApi, (message, token, msg) => {
            console.log('the token', token);

            /* Resolve enclosing promise with token */
            resolve(token); 
        })
    }));
}
在助手模块中应用这些更改后,您需要更新
componentWillMount()
组件挂钩,以正确集成这些方法,确保在成功获取两个令牌后,使用
{tokensAreLoaded:true}
更新组件状态:

componentWillMount() {

    /* Issue request for both tokens to get aquired */
    Promise.all([
        acquireToken(),
        acquireGraphToken()
    ])
    .then(([ token, graphToken ]) => {

        /* On resolving both requests, ensure tokens are value before proceeding or reject (as before) */
        if (token != '' && graphToken != '') {
            resolve(token);
        } else {
            reject(Error('promise failed'))
        }
    })
    .then(() => {

        /* On success, update state */
        this.setState({tokensAreLoaded: true});
    })
  }

希望这有帮助

我建议在获取令牌之前引入某种加载通知。您可以在
componentDidMount
中等待令牌,这样就不会阻塞堆栈

async componentDidMount() {
    try {
        const token = await this.getToken();
        this.setState({tokensAreLoaded: true, token});
    } catch (e) {
        throw new Error (e);
    }
}
getToken () {
    return new Promise((resolve, reject) => {
        const token = acquireToken();
        const graphToken = acquireGraphToken();

        if (token != '' && graphToken != '') {
            resolve(token);
        } else {
           reject(Error('promise failed'))
        }
    });
}
渲染
方法中:

render () {
    if (!this.state.tokensAreLoaded) {
        return (<p>Authorizing</p>);
    }
    return (
       // the stuff you want to display when token is ready
    )

}
render(){
如果(!this.state.tokensAreLoaded){
返回(授权

); } 返回( //令牌准备就绪时要显示的内容 ) }
您可以按照以下步骤操作@Rodney wormbecher您想在
render()
中等待承诺解决之前?@MaheerAli最好是在异步调用完成时触发应用程序渲染以重新渲染。@如果我似乎没有注意到我的代码和那里给出的答案之间的差异。newName已定义,但从未使用过。因此,不确定我缺少了什么。
acquireGraphToken
acquireToken
将始终返回null,因为回调将被异步调用
render () {
    if (!this.state.tokensAreLoaded) {
        return (<p>Authorizing</p>);
    }
    return (
       // the stuff you want to display when token is ready
    )

}