我试图将React与Flux架构结合使用,偶然发现了一个我无法处理的限制。 问题如下:
到目前为止,我想出的最佳解决方案是将内部调度包裹在setTimeout(f, 0)
中,但它看起来很可怕。
实际上问题非常普遍 - 如果每个新的调度基于先前的调度处理结果,我应该如何在没有调度嵌套的情况下组织调度链(不违反当前的Flux限制)。
有没有人有解决此类问题的好方法?
var selectItem(item) {
AppDispatcher.dispatch({
actionType: AppConstants.ITEM_SELECT,
item: item
});
}
// Item must be requested and selected.
// If it's in store - select it.
// Otherwise fetch and then select it.
SomeStore.dispatchToken = AppDispatcher.register((action) => {
switch(action.actionType) {
case AppConstants.ITEM_REQUESTED:
var item = SomeStore.getItem(action.itemId);
if (item) {
// Won't work because can't dispatch in the middle of dispatch
selectItem(item);
} else {
// Will work
$.getJSON(`some/${action.itemId}`, (item) => selectItem(item));
}
}
};
答案 0 :(得分:2)
setTimeout(f, 0)
是一个很好的技巧。我在最小通量here中做同样的事情。没有什么可怕的。 Javascript的concurrency model非常简单。
更强大的磁通调度程序实现应该为您处理。
答案 1 :(得分:2)
如果 ITEM_SELECT
是另一个Store
要处理的事件:
您正在寻找dispatcher.waitFor(array<string> ids): void
,它允许您使用SomeStore.dispatchToken
返回register()
来强制执行商店处理活动的顺序。
我们称之为OtherStore
的商店会处理ITEM_SELECT
事件,而应该处理ITEM_REQUEST
事件,但先调用dispatcher.waitFor( [ SomeStore.dispatchToken ] )
,然后再获取任何内容结果很有意思来自SomeStore
通过公共方法,例如SomeStore.getItem()
。
但,似乎SomeStore对ITEM_REQUEST
的内部状态没有任何作用,因此您只需将以下行移至OtherStore
有一些小的更改:
// OtherStore.js
case AppConstants.ITEM_REQUESTED:
dispatcher.waitFor( [ SomeStore.dispatchToken ] );// and don't even do this if SomeStore isn't doing anything with ITEM_REQUEST
var item = SomeStore.getItem(action.itemId);
if (item) {
// Don't dispatch an event, let other stores handle this event, if necessary
OtherStore.doSomethingWith(item);
} else {
// Will work
$.getJSON(`some/${action.itemId}`, (item) => OtherStore.doSomethingWith(item));
}
同样,如果另一家商店需要处理OtherStore.doSomethingWith(item)
的结果,他们也可以处理ITEM_REQUESTED
,但在继续之前请致电dispatcher.waitFor( [ OtherStore.dispatchToken ] )
。
答案 2 :(得分:0)
因此,在查看您的代码时,您是否正在设置&#34;已选择&#34;项目上的属性,以便在您的UI /组件中检查/选择它?如果是这样,只需制作您已经在的功能部分。
if(item) {
item.selected = true;
//we're done now, no need to create another Action at this point,
//we have changed the state of our data, now alert the components
//via emitChange()
emitChange();
}
如果您想要跟踪商店中当前选择的项目,只需将ID或对象作为私有变量,并进行类似设置。
var Store = (function(){
var _currentItem = {};
var _currentItemID = 1;
function selectItem(item) {
_currentItem = item;
_currentItemID = item.id;
emitChange();
}
(function() {
Dispatcher.register(function(action){
case AppConstants.ITEM_REQUESTED:
var item = SomeStore.getItem(action.itemId);
if (item) {
selectItem(item);
} else {
$.getJSON(`some/${action.itemId}`, (item) =>
selectItem(item);
}
});
})();
return {
getCurrentlySelectedItem: function() {
return _currentItem;
},
getCurrentlySelectedItemID: function() {
return _currentItemID;
}
}
})();
最终,您不必为所有事情创建动作。无论您正在操作的项目是什么,它都应该是某个域实体,管理该特定实体的状态是您的Store的工作。拥有其他内部功能通常是必需的,因此只需将selectItem(item)作为Store的内部功能,这样您就不必创建新的Action来访问它或使用它。
现在,如果您有跨存储问题,而另一个Store关心初始Store中某些数据的某些特定更改,那么waitFor(ids)函数将会进入。它会有效阻止执行直到第一个Store更新,然后另一个可以继续执行,确保其他商店的数据处于有效状态。
我希望这有意义并解决你的问题,如果没有,请告诉我,希望我能更好地归零。