Javascript承诺等待结果
我正在开发一个React应用程序,它将通过ADAL与Azure Ad进行身份验证。一切正常,但我需要在应用程序开始时加载JWT令牌。我想我将把我的两个函数包装起来,这两个函数在承诺中返回一个令牌,然后有条件地呈现它,但是出于某种原因,它不会“等待”我的承诺得到解决 欢迎任何帮助。干杯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
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
)
}