在运行时动态添加 epics 多次调用新添加的 epics
Dynamically adding epics during runtime calls the newly added epics multiple times
我的工作基于这些方向:https://redux-observable.js.org/docs/recipes/AddingNewEpicsAsynchronously.html
所以我在让这个测试执行 epics 时遇到问题,我是不是遗漏了什么?在任何情况下,代码都会解释发生了什么......
我希望我对 store.dispatch({type:'GO'})
的调用能够链接我所有的 epics。我看到我的减速器已连接,但 Epics 没有被调用。
fyi 我需要这个来测试我认为是错误的东西。在我的实际应用程序中,当我使用 epicLoader$.next(<someepic>)
动态加载新的史诗时,动态加载的史诗现在被调用了两次......但在这个测试起作用之前我无法证明这一点。
作为解决方法,我手动添加了我想动态添加的 epics,它工作正常,但在我的 POC 阶段这是不可能的。我需要从将被推送到应用程序的单独文件中加载 epics。
帮我欧比万...
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/mapTo';
import 'rxjs/add/operator/do';
import { Observable } from 'rxjs/Observable';
import {combineReducers, createStore, applyMiddleware} from 'redux';
import { createEpicMiddleware,combineEpics } from 'redux-observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
test('dynamicly loading epic calls it twice',done => {
let epic1 = (action$)=>action$
.ofType('GO')
.do((action)=>console.log('epic1',action))
.mapTo({type:'EPIC1'});
let epic2 = (action$,{epicLoader$})=>action$
.ofType('EPIC1')
.do((action)=>console.log('epic2',action))
.do(()=>epicLoader$.next(epic3))
.do(()=>epicLoader$.next(epic4))
.mapTo({type:'EPIC2'});
let epic3 = (action$)=>action$
.ofType('EPIC2')
.do((action)=>console.log('epic3',action))
.mapTo({type:'EPIC3'});
let epic4 = (action$)=>action$
.ofType('EPIC2')
.do((action)=>console.log('epic4',action))
.do(()=>done())
.mapTo({type:'EPIC4'});
const epic$ = new BehaviorSubject(combineEpics({epic1,epic2}));
const rootEpic = (action$, store, args) =>
epic$.mergeMap(epic =>
epic(action$, store, args)
);
const epicMiddleware = createEpicMiddleware(rootEpic,
{ dependencies: {
epicLoader$: epic$,
}});
const reducer =(state = {},action)=>{
console.log('reducer',action);
return state;
};
const store = createStore(
combineReducers({
reducer
}),
applyMiddleware(epicMiddleware)
);
//start up the chain of events.
store.dispatch({type:'GO'});
});
我认为所提供的代码存在两个问题:
向 combineEpics
提供对象,而不仅仅是参数
您正在将一个对象传递给 combineEpics
,但它应该只是普通的旧参数。这不同于 combineReducers
// bad
const epic$ = new BehaviorSubject(combineEpics({epic1,epic2}));
// good
const epic$ = new BehaviorSubject(combineEpics(epic1,epic2));
此处讨论了对传递对象的支持:https://github.com/redux-observable/redux-observable/issues/58。它还没有被支持,因为键是没有意义的,不像 combineReducers
.
当订阅 rootEpic 时,这确实会抛出一个错误,但不幸的是,由于 outstanding bug in rxjs
解构 store
而不是第三个依赖项参数
// bad
let epic2 = (action$,{epicLoader$})=>action$
// good
let epic2 = (action$,store,{epicLoader$})=>action$
修复这些后,它似乎可以正常工作:
我确实注意到 epic4
正在监听 EPIC2
,您可能实际上是想监听 EPIC3
?
我的工作基于这些方向:https://redux-observable.js.org/docs/recipes/AddingNewEpicsAsynchronously.html
所以我在让这个测试执行 epics 时遇到问题,我是不是遗漏了什么?在任何情况下,代码都会解释发生了什么......
我希望我对 store.dispatch({type:'GO'})
的调用能够链接我所有的 epics。我看到我的减速器已连接,但 Epics 没有被调用。
fyi 我需要这个来测试我认为是错误的东西。在我的实际应用程序中,当我使用 epicLoader$.next(<someepic>)
动态加载新的史诗时,动态加载的史诗现在被调用了两次......但在这个测试起作用之前我无法证明这一点。
作为解决方法,我手动添加了我想动态添加的 epics,它工作正常,但在我的 POC 阶段这是不可能的。我需要从将被推送到应用程序的单独文件中加载 epics。
帮我欧比万...
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/mapTo';
import 'rxjs/add/operator/do';
import { Observable } from 'rxjs/Observable';
import {combineReducers, createStore, applyMiddleware} from 'redux';
import { createEpicMiddleware,combineEpics } from 'redux-observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
test('dynamicly loading epic calls it twice',done => {
let epic1 = (action$)=>action$
.ofType('GO')
.do((action)=>console.log('epic1',action))
.mapTo({type:'EPIC1'});
let epic2 = (action$,{epicLoader$})=>action$
.ofType('EPIC1')
.do((action)=>console.log('epic2',action))
.do(()=>epicLoader$.next(epic3))
.do(()=>epicLoader$.next(epic4))
.mapTo({type:'EPIC2'});
let epic3 = (action$)=>action$
.ofType('EPIC2')
.do((action)=>console.log('epic3',action))
.mapTo({type:'EPIC3'});
let epic4 = (action$)=>action$
.ofType('EPIC2')
.do((action)=>console.log('epic4',action))
.do(()=>done())
.mapTo({type:'EPIC4'});
const epic$ = new BehaviorSubject(combineEpics({epic1,epic2}));
const rootEpic = (action$, store, args) =>
epic$.mergeMap(epic =>
epic(action$, store, args)
);
const epicMiddleware = createEpicMiddleware(rootEpic,
{ dependencies: {
epicLoader$: epic$,
}});
const reducer =(state = {},action)=>{
console.log('reducer',action);
return state;
};
const store = createStore(
combineReducers({
reducer
}),
applyMiddleware(epicMiddleware)
);
//start up the chain of events.
store.dispatch({type:'GO'});
});
我认为所提供的代码存在两个问题:
向 combineEpics
提供对象,而不仅仅是参数
您正在将一个对象传递给 combineEpics
,但它应该只是普通的旧参数。这不同于 combineReducers
// bad
const epic$ = new BehaviorSubject(combineEpics({epic1,epic2}));
// good
const epic$ = new BehaviorSubject(combineEpics(epic1,epic2));
此处讨论了对传递对象的支持:https://github.com/redux-observable/redux-observable/issues/58。它还没有被支持,因为键是没有意义的,不像 combineReducers
.
当订阅 rootEpic 时,这确实会抛出一个错误,但不幸的是,由于 outstanding bug in rxjs
解构 store
而不是第三个依赖项参数
// bad
let epic2 = (action$,{epicLoader$})=>action$
// good
let epic2 = (action$,store,{epicLoader$})=>action$
修复这些后,它似乎可以正常工作:
我确实注意到 epic4
正在监听 EPIC2
,您可能实际上是想监听 EPIC3
?