【发布时间】:2017-11-15 11:30:34
【问题描述】:
我在我的应用程序中使用了以下史诗来处理 api 请求:
action$ => {
return action$.ofType(actions.requestType)
.do(() => console.log('handled epic ' + actions.requestType))
.switchMap((action) => (
Observable.create((obs) => {
obs.next({ type: type, value: action.value, form: action.form });
})
.debounceTime(250)
.switchMap((iea) => (
Observable.ajax(ajaxPost(url(iea.value), body ? body(iea.value) : action.form))
.mergeMap(payload => {
return Observable.merge(
Observable.of(actions.success(payload)),
/* some other stuff */
);
})
.catch(payload => {
return [actions.failure(payload)];
})
))
))
.takeUntil(action$.filter((a) => (a.type === masterCancelAction))
.repeat();
};
基本上,每当我执行一个 api 请求时,我都会发送一个请求动作。如果我快速发送另一个请求,则使用 debounceTime 忽略前一个请求。此外,可以使用 masterCancelAction 取消请求,并在取消时 repeat() 重新启动史诗。这部史诗在所有情况下都能按预期工作。
失败案例发生在用户在请求期间使用浏览器返回。在这种情况下,我将 masterCancelAction 触发到请求。但是,在作为 masterCancelAction 的结果的相同执行上下文中,另一个请求操作分派以对同一史诗执行新请求,但是没有发生 api 请求(尽管确实发生了 console.log),就好像没有重复一样()。在发生取消的其他情况下,不会从相同的执行上下文调用下一个请求并且它工作正常,所以在这种情况下,我的代码似乎没有给重复机会重新启动史诗?
我发现一个肮脏的解决方法是在取消后调度的请求上使用 setTimeout(dispatch(action), 0)。这似乎允许 repeat() 执行。我尝试将不同的调度程序传递给重复,但这似乎没有帮助。此外,将 takeUntil 和 repeat 附加到我的内部 switchMap 可以解决问题,但是其他情况下我的下一个请求未在同一个调用堆栈中执行会失败。
有没有一种方法可以在不使用 setTimeout 的情况下解决这个问题?也许这不是重复相关的问题,但似乎是这样。
使用 rxjs 5.0.3 和 redux-observable 0.14.1。
【问题讨论】:
标签: rxjs rxjs5 redux-observable