使用可观察对象中的函数与创建许多动作/史诗

时间:2017-06-30 17:56:22

标签: redux redux-observable

我刚刚开始使用redux-observable,我在多种方法之间做出相同的决定时遇到了麻烦。下面是两个执行某些逻辑以响应操作的方法的示例:

方法A(史诗):

function epic1(action$){
    return action$.ofType(FOO)
        .map(action => something(action.payload))
        .map(result => ({type: BAR}));
}

function epic2(action$){
    return action$.ofType(BAR)
        .map(action => something(action.payload));
        // potentially returning actions for a third epic, etc.
}

方法B(功能):

function helperFunction(result){
    // something that returns an action eventually
}

function singleEpic(action$){
    action$.ofType(FOO)
        .map(action => something(action.payload))
        .map(helperFunction);
}

您可以想象每个模式都会向外扩展,而且功能实际上也很复杂。做方法A有很多开销吗?这些行为是否会在到达epic2之前通过整个redux循环,这是否在任何人的经历中都是显而易见的?

到目前为止,我绝对想要制作尽可能多的史诗,因为它们最终变得非常小而且简单,但我不确定成本。

2 个答案:

答案 0 :(得分:1)

我可以使用redux-saga从项目中提供我的经验。我认为性能特征和设计权衡非常相似。

在案例A中可能会出现某些性能损失。但是,除非出现真正的错误,否则它不应该是您平均SPA的重要考虑因素。 YMMV如果您正在开发游戏或其他性能密集型的东西。从这个角度来看,创造更少的传奇似乎是微观优化。

我们非常倾向于类似于你所描述的方法B的东西。我们通常会为类似传奇的家庭创建工厂,非常类似于以下示例:

const factory = ({ actionType, mapper, actionCreator }) => (action$) =>
  action$.ofType(actionType)
    .map(action => mapper(action.payload))
    .map(actionCreator);

const epic = factory({
  actionType: 'FOO',
  mapper: payload => payload + 1,
  actionCreator: newPayload => ({ type: 'BAR', payload: newPayload })
});

在这个人为的例子中,它可能没那么有意义,因为抽象的认知开销高于你从中得到的,但你得到了这个想法。我们也采用了非常类似的减速器策略。

但是,如果可能的话,我会警告不要像你用epic1epic2等描述的那样创建动作的瀑布。我相信如果你的代码中存在太多隐含的相互依赖性,它最终将更难调试。虽然在过去的某些框架中可能远不如双向绑定链(例如Ember)。

所以一般来说,我的建议是创造尽可能多的小传奇,创造小帮手来帮助你构建它们。但是对于更复杂的异步流更喜欢更长的更明确的史诗(而不是有太多的合作史诗)。

答案 1 :(得分:0)

方法A会慢一些,因为它会通过reducer和epics的整个redux链。 (史诗本质上是中间件)。这有多慢,重要的程度取决于你认为更易于理解和清晰理解的内容。

我认为,如果你有一个FOO动作,它应该执行一些帮助功能,并最终启动另一个史诗,你不需要三个单独的史诗。如果可能的话,不要开始任何后续行动对我来说更有意义。

然而,如果你确实需要合并史诗,那么创建一个处理'瀑布'类型流的史诗是有意义的。对于这个人为的例子,我肯定不会做方法A.如果你只需要运行一些辅助逻辑,那么直接调用该函数。没有必要向上游行走,所以你可以沿着河流骑行,这样你就可以到达原来的位置。

相关问题