ReactJS首次加载页面触发SignalR未授权错误,二次刷新才正常如何解决
问题原因
你的代码中getURL是异步请求,调用后不会等待接口返回就直接执行了SignalR连接初始化逻辑。首次加载时localStorage里还没存上接口返回的access_token,所以连接校验失败返回Error: Unauthorized。二次刷新时localStorage里已经有了上一次请求成功存储的token,所以可以正常连接。
修复方案
把SignalR连接初始化的逻辑全部移动到getURL的成功回调中,确保拿到有效token之后再初始化连接,参考修复后的代码:
export default class Dashboard extends Component { constructor(props) { super(props) this.state = { signalRURL: 'https://****/?hub=broadcast', accessToken: '', alertData: {} } // 把连接实例挂到this上方便后续操作 this.hubConnection = null } getURL = () => { return new Promise((resolve, reject) => { return axios({ url: 'https://*****/api/SignalRConnection', method: "get", headers: { "content-type": "application/json", "Access-Control-Allow-Origin": "*" }, }) .then(response => { resolve(response.data); }) .catch(error => { reject(error); }); }); } componentDidMount = () => { this.getURL().then(signalRConfig => { // 拿到token之后再初始化连接 const options = { // 直接用接口返回的token,不用读localStorage更稳妥 accessTokenFactory: () => signalRConfig.accessToken }; this.hubConnection = new SignalR.HubConnectionBuilder() .withUrl(this.state.signalRURL, options) .configureLogging(SignalR.LogLevel.Information) .build(); this.hubConnection.on('notify', data => { this.setState({alertData: data}) console.log(data); }); this.hubConnection .start() .catch(error => console.error(error)); this.hubConnection.serverTimeoutInMilliseconds = 6000000; this.hubConnection.keepAliveIntervalInMilliseconds = 3000000; this.hubConnection.onclose((error) => { this.hubConnection.start(); console.error(`Something went wrong: ${error}`); }); }) .catch(err => { console.log("获取SignalR连接凭证失败", err) }) } // 新增组件卸载逻辑,避免内存泄漏 componentWillUnmount = () => { if (this.hubConnection) { this.hubConnection.stop() } } render() { return ( <div> </div> ) } }
额外优化建议
- 如果token存在过期逻辑,可以在
accessTokenFactory里加刷新token的逻辑,避免连接有效期内token失效 - 可以给连接初始化添加最多N次重试逻辑,避免偶发的接口波动导致连接失败
- 不需要的日志可以及时删除,避免生产环境泄露敏感信息
内容的提问来源于stack exchange,提问作者Vishal K.
相关产品推荐
相关产品推荐

