Ian*_*ber 20 javascript reactjs reactjs-flux
在我的Flux架构的React应用程序中,我正在从商店中检索数据,并且想要创建一个操作来请求该信息(如果它不存在).但是我遇到了调度员已经调度的错误.
我想要的代码是这样的:
getAll: function(options) {
options = options || {};
var key = JSON.stringify(options);
var ratings = _data.ratings[key];
if (!ratings) {
RatingActions.fetchAll(options);
}
return ratings || [];
}
Run Code Online (Sandbox Code Playgroud)
但是,当调度程序已经使用该消息调度操作时,间歇性地失败Invariant Violation: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch..我经常提出请求以响应应用程序状态的变化(例如日期范围).我发出请求的组件,响应来自的更改事件AppStore具有以下内容:
getStateFromStores: function() {
var dateOptions = {
startDate: AppStore.getStartISOString(),
endDate: AppStore.getEndISOString()
};
return {
ratings: RatingStore.getAll(dateOptions),
};
},
Run Code Online (Sandbox Code Playgroud)
我知道事件链接是一个Flux反模式,但我不确定哪种架构在尚不存在时检索数据更好.目前我正在使用这个可怕的黑客:
getAll: function(options) {
options = options || {};
var key = JSON.stringify(options);
var ratings = _data.ratings[key];
if (!ratings) {
setTimeout(function() {
if (!RatingActions.dispatcher.isDispatching()) {
RatingActions.fetchAll(options);
}
}, 0);
}
return ratings || [];
},
Run Code Online (Sandbox Code Playgroud)
什么是更好的架构,避免事件链接或调度程序错误?这真的是事件链吗?我只想根据应用程序设置的参数更改数据.
谢谢!
我发生了特定错误,因为我的商店在操作调度期间发出了更改事件,而它仍然在侦听器中循环.这意味着由于商店中的数据更改而触发操作的任何侦听器(即组件)将中断调度.我通过在调度完成后发出更改事件来修复它.
所以这:
this.emit(CHANGE_EVENT);
Run Code Online (Sandbox Code Playgroud)
成为
var self = this;
setTimeout(function() { // Run after dispatcher has finished
self.emit(CHANGE_EVENT);
}, 0);
Run Code Online (Sandbox Code Playgroud)
还是有点hacky(可能会重写所以不需要setTimeout).打开解决架构问题的解决方案,而不是此实现细节.
您在上一次调度过程中获得调度的原因是您的商店在处理程序中同步调度操作(调用操作创建者)以执行其他操作.调度程序在技术上调度,直到所有已注册的回调都已执行.因此,如果您从任何一个已注册的回调中分派新操作,您将收到该错误.
但是,如果您执行某些异步工作,例如发出ajax请求,您仍然可以在ajax回调或异步回调中调度操作.这是有效的,因为只要调用了异步函数,它就会立即继续执行该函数并将回调放在事件队列中.
正如Amida所指出的那样,在答案的评论中,选择是否从商店发出ajax请求以响应某个操作,或者是否在商店中进行操作是一个选择问题.关键是商店应该只改变其状态以响应动作,而不是在ajax/async回调中.
在您的特定情况下,如果您希望从商店进行ajax调用,则可以通过此类商店的注册回调来举例说明:
onGetAll: function(options) {
// ...do some work
request(ajaxOptions) // example for some promise-based ajax lib
.then(function(data) {
getAllSuccessAction(data); // run after dispatch
})
.error(function(data) {
getAllFailedAction(data); // run after dispatch
});
// this will be immediately run during getAllAction dispatch
return this.state[options];
},
onGetAllSuccess: function(data) {
// update state or something and then trigger change event, or whatever
},
onGetAllFailed: function(data) {
// handle failure somehow
}
Run Code Online (Sandbox Code Playgroud)
或者您可以将ajax调用放入您的操作创建者,并从那里调度"成功/失败"操作.
就我而言,我通过操作/操作创建者获取数据。存储只是接收操作有效负载的转储位置。
这意味着我将在一个操作中“fetchall”,然后将结果传递到商店,商店将对其执行任何操作,然后发出更改事件。
有些人像我一样考虑使用商店,另一些人则像你一样考虑。Facebook 的一些人使用“我的”方法:
我认为这样对待你的商店可能会避免调度问题,但我可能是错的。
一个有趣的讨论是:https://groups.google.com/forum/#!topic /reactjs/jBPHH4Q-8Sc
Jing Chen(Facebook 工程师)解释了她对如何使用商店的看法。
| 归档时间: |
|
| 查看次数: |
17431 次 |
| 最近记录: |