【发布时间】:2017-02-16 14:14:34
【问题描述】:
首先是这个很棒的图书馆的许多道具!不过,我仍在为一个用例而苦苦挣扎。我想先调用另一个史诗并等到它完成后再继续当前的史诗。假设我有一个用户可以更改内容的表单。在将其他数据加载到表单之前,我想先保存当前的更改。对此有什么想法吗?
【问题讨论】:
标签: reactjs redux rxjs redux-observable
首先是这个很棒的图书馆的许多道具!不过,我仍在为一个用例而苦苦挣扎。我想先调用另一个史诗并等到它完成后再继续当前的史诗。假设我有一个用户可以更改内容的表单。在将其他数据加载到表单之前,我想先保存当前的更改。对此有什么想法吗?
【问题讨论】:
标签: reactjs redux rxjs redux-observable
听起来如你所愿:如果一部史诗想要开始另一部史诗的作品并且 等待它完成后再继续。
一种方法是(使用伪名称),当接收到初始操作 LOAD_OTHER_DATA 时,您立即开始侦听单个 SAVE_FORM_FULFILLED,这表明表单已保存(我们稍后会启动它) .收到后,我们将mergeMap(或switchMap,在这种情况下无关紧要)加入我们的调用以加载其他数据loadOtherDataSomehow() 并执行常规业务。最后,开始实际保存我们正在等待的表单的技巧是在整个链的末尾添加一个startWith() - 这将发出并调度操作以实际保存表单。
const saveFormEpic = (action$, store) =>
action$
.ofType('SAVE_FORM')
.switchMap(() =>
saveFormSomeHow(store.getState().formDataSomewhere)
.map(details => ({
type: 'SAVE_FORM_FULFILLED'
}))
);
const loadOtherDataEpic = action$ =>
action$
.ofType('LOAD_OTHER_DATA')
.switchMap(() =>
action$.ofType('SAVE_FORM_FULFILLED')
.take(1) // don't listen forever! IMPORTANT!
.mergeMap(() =>
loadOtherDataSomeHow()
.map(otherData => ({
type: 'LOAD_OTHER_DATA_FULFILLED',
payload: otherData
}))
)
.startWith({
type: 'SAVE_FORM'
})
);
你没有提到你的加载和保存是如何工作的,所以这只是你需要为你的用例修改的伪代码。
【讨论】:
@jayphelps,我只想对您回答的所有问题表示感谢,他们确实帮助我解决了许多问题。
我正在尝试制定我的问题,发现您已经在这里回答了它并设法使用您的示例解决了我的问题。
我的示例有/有 2 个我想要/ed 互相调用的 expics:
const requestNameEpic = action$ =>
action$.ofType("REQUEST_NAME")
.switchMap(({id}) =>
Observable.of(`name returned by 'ajax' call, using id: ${id}`) // Ajax simulation
.delay(1000)
.map(name => ({type: "LOAD_NAME", name}))
);
const requestAgeEpic = action$ =>
action$.ofType("REQUEST_AGE")
.switchMap(({name}) =>
Observable.of(`age returned by 'ajax' call, using name: [${name}]`)
.delay(1000)
.map(age => ({type: "LOAD_AGE", age}))
);
我设法解决它的方法是:
const requestDetailsEpic = action$ =>
action$.ofType("LOAD_NAME")
.map(({name}) => ({type: "REQUEST_AGE", name}));
所以调度 REQUEST_NAME 也会调度 REQUEST_AGE,但我永远无法只调度 LOAD_NAME。
我重构了您的示例以获得:
const requestDetailsEpic = action$ =>
action$.ofType("REQUEST_DETAILS")
.switchMap(({id}) =>
action$.ofType("LOAD_NAME")
.take(1) // don't listen forever! IMPORTANT!
.map(({name}) => ({type: "REQUEST_AGE", name}))
.startWith({type: "REQUEST_NAME", id})
);
再次感谢您在 redux-observable 上所做的所有出色工作以及所有社区的支持。
【讨论】: