我目前正在使用通常与 ReactJS 相关的通量模式开发原型应用程序。
在 Facebook通量/聊天示例中,有两个商店,ThreadStore和UnreadThreadStore。后者提供了一个同步读取前者内容的getAll方法。
我们遇到了一个问题,即派生存储中的操作太昂贵而无法同步执行,并且理想情况下会委托给异步进程(Web Worker、服务器跳闸),我们想知道如何解决这个问题。
我的同事建议从吸气剂返回一个承诺,即
# MyView
componentDidMount: function () {
defaultState = { results: [] };
this.setState(defaultState);
DerivedStore.doExpensiveThing()
.then(this.setState);
}
我对此并不完全满意。感觉就像是打破了模式,因为视图是变化的主要接受者,而不是商店。这是我们一直在探索的另一种途径 - 视图安装事件会发送一个更新派生数据的需求(如果需要)。
# DerivedStore
# =========================================================
state: {
derivedResults: []
status: empty <fresh|pending|empty>
},
handleViewAction: function (payload) {
if (payload.type === "refreshDerivedData") {
this.state.status = "pending"; # assume an async action has started
}
if (payload.type === "derivedDataIsRefreshed") {
this.state.status = "fresh"; # the async action has completed
}
this.state.derivedResults = payload.results || []
this.notify();
}
# MyAction
# =========================================================
MyAction = function (dispatcher) {
dispatcher.register(function (payload) {
switch (payload) {
case "refreshDerivedData":
doExpensiveCalculation()
.then(function(res) {
dispatcher.dispatch({
type: "derivedDataIsRefreshed",
results: res
})
})
);
}
});
};
# MyView
# =========================================================
MyView = React.createClass({
componentDidMount: function () {
if (DerivedStore.getState().status === "empty") {
Dispatcher.dispatch("refreshDerivedData");
}
},
getVisibility: function () {
return DerivedStore.getState().status === "pending" ? "is-visible" : ""
},
render: function () {
var state = DerivedStore.getState()
, cx = React.addons.classSet
, classes = cx({
"spinner-is-visible": state.status === "pending"
});
return <div {classes}>
<Spinner /> # only visible if "spinner-is-visible
<Results results={state.derivedResults}/> # only visible if not...
</div>;
}
});
# MyService
# =========================================================
# ensure derived data is invalidated by updates in it's source?
OriginalStore.addListener(function () {
setTimeout(function () {
dispatcher.dispatch({
type: "refreshDerivedData"
})
}, 0);
});
我喜欢这种方法的地方在于视图将 DerivedStore 视为它的视图模型,并且此类视图主要对其视图模型的新鲜度感兴趣。然而,我担心的是商店可能不同步。
那么我的问题:
- 承诺方法可以接受吗?
- 第二种方法更好/更差?如果是这样,为什么?
- 是否存在解决此问题的“规范”方法?
PS:抱歉,如果此代码中有任何基本的 linting 错误,我在过去 3 个月一直在 Coffeescript 工作,它破坏了我的 linting 能力......