Redux-observable 返回一些示例数据

Redux-observable returning some sample data

我正在使用 redux-observable,我需要 return 一些示例数据作为 Observable。我的 epics

之一中有以下代码
const sampleFilteredStores = Observable.of([{ type: 'FILTERED_STORES', store: 'a' }, { type: 'FILTERED_STORES', store: 'b' }]);
const filteredStores$ = action$.ofType('SEARCH_STORES').mapTo(Observable.of(sampleFilteredStores).mergeAll());
return filteredStores$;

然而,当我 运行 这样做时,我得到一个错误

instrument.js:56 未捕获错误:操作必须是简单的 objects。使用自定义中间件进行异步操作。(…)

我做错了什么,我该如何解决?

调查

对于您提供的示例代码,我们需要做的第一件事是缩进和格式化代码,以便更容易理解发生了什么。

const somethingEpic = action => {
  const sampleFilteredStores = Observable.of([
    { type: 'FILTERED_STORES', store: 'a' },
    { type: 'FILTERED_STORES', store: 'b' }
  ]);
  const filteredStores$ = action$.ofType('SEARCH_STORES')
    .mapTo(
      Observable.of(sampleFilteredStores)
        .mergeAll()
    );

  return filteredStores$;
};

具体如何格式化代码是您的选择,但我个人认为 这样的代码更具可读性。它将帮助您进行调试,但也会显着帮助您的代码的任何未来维护者理解您的意图。

mapTo

现在我可以立即看到一个问题,那就是您将一个 Observable 传递给 mapTo,这在 Rx 中是非常不寻常的。这肯定不是 100% 错误,但 99.99% 甚至 0.01% 都会有更清晰的方式来显示所需的意图。

Observable.of

进一步挖掘,我看到 Observable.of.

的两种用法

第一个突出的是你将一个 Observable 传递给 Observable.ofObservable.of(sampleFilteredStores) 这里适用与 mapTo 相同的建议,这是非常不常见的,不推荐,因为它会创建高阶 Observables 不必要。我确实看到你使用 mergeAll() 来展平它,但这给了你一个 Observable,它基本上与没有间接寻址的 sampleFilteredStores 相同。

当我深入挖掘时,我注意到另一个微妙但关键的事情,你将一个 数组 的动作传递给 Observable.of。这也是非常可疑的,因为这意味着您创建的 Observable 只发出两个动作的数组,而不是直接连续发出这两个动作。如果后者是您想要的,那么您需要直接将 object 作为参数本身传递。 Observable.of(action1, action2, action3, ...etc)。您可能对看到有人使用 Observable.from 传递数组感到困惑,但这与 Observable.of

不同

根本原因

结合这些发现,我现在可以看到这部史诗实际上 发出 一个 Observable,而不是动作,这就是为什么你从 redux 收到错误。该 Observable 本身实际上会发出一系列操作,因此即使您已将 Observable 展平,您仍然会收到相同的错误。

解决方案

看来所提供的代码可能是为了简化您的问题或在您学习 Rx 或 redux-observable 时设计的。但是在这种特定情况下,我相信你想听 SEARCH_STORES 并且在接收到时按顺序分派两个 FILTERED_STORES 类型的动作,具有不同的 store 值。

使用惯用的 Rx,可能看起来像这样:

const somethingEpic = action => {
  return action$.ofType('SEARCH_STORES')
    .mergeMap(() => Observable.of(
      { type: 'FILTERED_STORES', store: 'a' },
      { type: 'FILTERED_STORES', store: 'b' }
    ))
};

这里我们使用的是 mergeMap,但是由于 Observable.of 我们在同步发射中展平,所以我们也可以使用 switchMapconcatMap,他们本来可以相同的净效应——但对于发出异步信号的 Observable 来说情况并非如此!因此,一定要研究各种扁平化策略运算符。

这条链可以描述为:每当我们收到 object 且 属性 type 等于 SEARCH_STORES 时,将其映射到两个 [=88= 的 Observable ]s(FILTERED_STORES 动作)按顺序同步发出。

关闭

希望这对您有所帮助!在学习和使用 redux-observable 时要记住的一件事是,它几乎完全是 "just RxJS" 恰好在处理 object,即 "actions"。所以正常的,惯用的 Rx 是正常的惯用 redux-observable。与您可能遇到的问题相同。唯一真正的区别是 redux-observable 将单个 ofType 运算符作为 shorthand 提供给 filter(如文档所述)。如果您将来遇到 Rx 问题,您可能会发现重构示例以使用 filter 并将它们表述为与 redux-observable 无关,因为 Rx 社区显然更大!