我正在使用redux-observable,我需要将一些示例数据作为Observable返回。我的一部史诗中有以下代码
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未捕获错误:操作必须是普通对象。使用自定义中间件进行异步操作。(...)
我在这里做错了什么,如何解决这个问题?
答案 0 :(得分:0)
对于您提供的示例代码,我们需要做的第一件事是缩进并格式化代码,以便更容易理解正在发生的事情。
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$;
};
确切地说,如何格式化代码是您的选择,但我个人发现之类的更具可读性。它将帮助您调试,但也可以帮助您的代码的任何未来维护者了解您的意图。
现在我可以立即看到一个问题,即你将一个Observable传递给mapTo
,这在Rx中非常不寻常。它在100%的时间内肯定不是错误,但99.99%甚至在0.01%中都会有更明确的方式来显示所需的意图。
进一步深入研究,我看到Observable.of
的两个用法。
第一个突出显示的是你将一个Observable传递给Observable.of
:Observable.of(sampleFilteredStores)
这里适用与mapTo
相同的建议,这是非常罕见的,不建议使用,因为它会创建更高的顺序不必要地观察。我确实看到你使用mergeAll()
来展平它,但是这会给你一个Observable,它基本上与没有间接的sampleFilteredStores
相同。
当我深入挖掘时,我会注意到另一个微妙但重要的事情,就是将数组的动作传递给Observable.of
。这也是高度可疑的,因为这意味着您创建一个Observable,它只发出两个动作的数组,而不是直接顺序发出这两个动作。如果后者是您的意图,则需要将对象直接作为参数传递。 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
我们在同步发布的情况下展开,我们也可以使用switchMap
或concatMap
相同的净效果 - 但是Observables发出异步的情况并非如此!因此,请务必研究各种扁平化策略运营商。
这个链可以描述为:每当我们收到属性type
等于SEARCH_STORES
的对象时,将它映射到两个对象(FILTERED_STORES
动作)的Observable,它们顺序发出并且同步。
希望这有帮助!学习和使用redux-observable时要记住的一件事是,它几乎完全是"只是RxJS"恰巧是处理"动作"的对象。所以正常的,惯用的Rx是正常的惯用的redux-observable。与您可能遇到的问题相同。唯一真正的区别是redux-observable提供单ofType
运算符作为filter
的简写(正如文档描述的那样)。如果您将来遇到Rx问题,您可能会发现重构示例以使用filter
并将它们与redux-observable无关,因为Rx社区显然要大得多!