我认为你不应该执行同步 AJAX 调用。
我不知道你的具体实现细节,但让我们想象一下,我们遇到了page/with/dynamic/data 需要身份验证:
var getStateFromStores = function() {
return {
authToken: AuthStore.getToken(),
dynamicData: FooStore.getAll()
}
}
var PageWithDynamicData = React.createClass({
getInitialState: function() {
return getStateFromStores();
},
componentDidMount: function() {
AuthStore.addChangeEventListener(this._onChange);
FooStore.addChangeEventListener(this._onChange);
},
componentWillUnmount: function() {
AuthStore.removeChangeEventListener(this._onChange);
FooStore.removeChangeEventListener(this._onChange);
},
render: function() {
if (!authToken || dynamicData.length == 0) {
return (
<p>Loading</p>
)
}
if (dynamicData.length == 0) { //we could be authenticated but dynamic datas are not retrievied yet
return (
<p>Loading</p>
)
}
return dynamicData.map(function (data) {
return <Foo data={data}/>
});
}
_onChange: function() {
this.setState(getStateFromStores());
}
});
AuthStore 可能应该将token 存储在其缓存中,并在第一次调用AuthStore.getToken() 时通过ajax 调用检索它。当这个 ajax 调用解析时,它会触发一个动作,例如TOKEN_RECEIVED。 AuthStore 将通过更新其内部token 状态来响应此操作以存储收到的token,因此下次我们需要它时,我们不需要再进行一次ajax 调用。然后,AuthStore 发出变化。
把它们放在一起:
状态1:用户第一次点击页面
- 用户点击
page/with/dynamic/data
- 您的
PageWithDynamicData 通过getStateFromStores 获取其初始状态
-
AuthStore.getToken() 被调用,此时它没有任何令牌,所以他触发了一个 ajax 调用(可能通过一些 WebAPIUtils 模块)来检索它(异步)。
-
FooStore.getAll() 被调用。同样,缓存中没有数据,因此调用 API 以检索数据(异步)。
- 由于缺少
this.state.authToken 和this.state.dynamicData,PageWithDynamicData 呈现在其加载状态
例子:
++++++++++++++++++++++
+ +
+ "loading" +
+ +
++++++++++++++++++++++
状态2:在token之前收到动态数据
这是完全合理的,因为我们运行的是异步请求。让我们看看会发生什么:
- 动态数据的 ajax 请求解析并触发
FOO_DATA_RECEIVED 操作。
-
FooStore 通过更新其内部状态以包含接收到的数据来响应此操作。
-
FooStore 发出变化
-
AuthStore.getToken() 已经挂起,所以我们什么也不做(这可以通过 Promise 完成,但这超出了这个问题的范围)
-
FooStore.getAll() 现在返回获取的数据
-
PageWithDynamicData 的渲染与之前完全相同,因为我们没有令牌。
出现同样的渲染:
++++++++++++++++++++++
+ +
+ "loading" +
+ +
++++++++++++++++++++++
状态 3:我们收到令牌
- 从服务器获取的请求解析并触发操作
TOKEN_RECEIVED
-
AuthStore 通过使用接收到的令牌更新其内部状态并发出更改来响应此操作
-
PageWithDynamicData 接收更改并且对 AuthStore.getToken() 和 FooStore.getAll() 的调用现在返回正确的数据
-
PageWithDynamicData 现在呈现数据:
页面现在将数据呈现给经过身份验证的用户:
++++++++++++++++++++++
+ +
+ - "some data" +
+ - "another one" +
+ - "..." +
+ +
++++++++++++++++++++++
重要提示:这不是“如何在我的 React 应用程序中处理身份验证”的答案,因为在这种情况下,我们可能应该使用一些会话存储或其他什么。但这里的重点是展示我们如何“等待”某事发生,然后再做任何其他事情,这要归功于 Flux 来保持单向数据流。