一种方法是(使用伪名称),当接收到初始操作时,API_GET_REQUEST
您会立即开始侦听单个INITIALIZE_FULFILLED
,这表明初始化(或其他)已完成——我们实际上将在稍后启动它。收到后,我们mergeMap
(或switchMap
您的用例中的任何一个)将其加入我们的调用中,以发出其他 ajax 请求并执行常规业务。最后,启动我们正在等待的实际初始化的技巧是startWith()
在整个链的末尾添加 a ——它将发出并调度另一个史诗正在等待的动作。
const initializeEpic = action$ =>
action$.ofType('INITIALIZE')
.switchMap(() =>
someHowInitialize()
.map(() => ({
type: 'INITIALIZE_FULFILLED'
}))
);
const getRequestEpic = (action$, store) =>
action$.ofType('API_GET_REQUEST')
.switchMap(() =>
action$.ofType('INITIALIZE_FULFILLED')
.take(1) // don't listen forever! IMPORTANT!
.switchMap(() => {
let url = store.getState().apiDomain + action.payload;
return ajax(get(url))
.map(xhr => ({
type: types.API_RESPONSE,
payload: xhr.response
}))
.catch(error => Observable.of({
type: 'API_ERROR',
payload: error
}));
})
.startWith({
type: 'INITIALIZE'
})
);
你没有提到一切是如何工作的,所以这只是你需要为你的用例修改的伪代码。
综上所述,如果您在此位置之外从不调用该初始化,您也可以直接将该代码包含在单个史诗本身中,或者只是创建一个对其进行抽象的辅助函数。将它们作为单独的史诗通常意味着您的 UI 代码可以独立地触发它们中的任何一个——但为了测试目的将它们分开可能仍然很好。只有你可以打那个电话。
const getRequestEpic = (action$, store) =>
action$.ofType('API_GET_REQUEST')
.switchMap(() =>
someHowInitialize()
.mergeMap(() => {
let url = store.getState().apiDomain + action.payload;
return ajax(get(url))
.map(xhr => ({
type: types.API_RESPONSE,
payload: xhr.response
}))
.catch(error => Observable.of({
type: 'API_ERROR',
payload: error
}));
})
.startWith({ // dunno if you still need this in your reducers?
type: 'INITIALIZE_FULFILLED'
})
);