Jon*_*man 6 rxjs redux-observable
我正在尝试创建一个简单的redux-observable史诗,它可以去抖动并且可以取消.我的代码:
export const apiValidate = action$ => {
return action$.ofType(validateRequestAction)
.debounceTime(250)
.switchMap((action) => (
Observable.ajax({
url: url,
method: 'GET',
crossDomain: true,
headers: {
"Content-Type": 'application/json'
},
responseType: 'json'
})
.map(payload => (new APISuccessValidate()))
.takeUntil(action$.ofType(validateCancelAction))
.catch(payload => ([new APIFailureValidate()]))
));
};
Run Code Online (Sandbox Code Playgroud)
代码有时只能工作.根据服务器响应的速度,我相信可能会出现两种情况中的一种.
场景1(工作):
Time 0ms - Fire validateRequestAction
Time 250ms - Ajax request occurs
Time 251ms - Fire validateCancelAction
Time 501ms - validateCancelAction passes debounce and cancels properly
Nothing else occurs
Run Code Online (Sandbox Code Playgroud)
场景2(破碎)
Time 0ms - Fire validateRequestAction
Time 250ms - Ajax request occurs
Time 251ms - Fire validateCancelAction
Time 400ms - Ajax returns, APISuccessValidate action fired
Time 501ms - validateCancelAction passes debounce and there is nothing to cancel
Run Code Online (Sandbox Code Playgroud)
有没有办法可以编写我的史诗,只有validateCancelAction可以绕过debounceTime并取消ajax调用而无需等待?
谢谢!
你实际上只是在缩减你的匹配validateRequestAction,但你.takeUntil(action$.ofType(validateCancelAction))没有任何去抖动.我可能错了,但是如果在动作通过去抖动之前可以发送取消动作,那么它原本要取消的动作将不会被取消,因为ajax请求还没有开始,也没有这个takeUntil.通过不允许取消直到您的副作用(在这种情况下为ajax)实际开始并且takeUntil正在倾听可能的取消,可以避免这种竞赛.
在UI中,在设置redux中的某个状态之前,您不会让用户取消.由于我们的史诗需要告诉redux何时翻转它,我们需要发出一个我们将在reducers中监听的动作.
最简单的方法是使用startWith运算符:
export const apiValidate = action$ => {
return action$.ofType(validateRequestAction)
.debounceTime(250)
.switchMap((action) => (
Observable.ajax({
url: url,
method: 'GET',
crossDomain: true,
headers: {
"Content-Type": 'application/json'
},
responseType: 'json'
})
.map(payload => (new APISuccessValidate()))
.takeUntil(action$.ofType(validateCancelAction))
.catch(payload => ([new APIFailureValidate()]))
.startWith({ type: 'validateRequestActionStarted' }) // <-- here
));
};
Run Code Online (Sandbox Code Playgroud)
所以在这个例子中,一些reducer会监听validateRequestActionStarted并改变一些状态,UI会知道我们应该给他们取消的能力.
一种完全不同的防止这种竞赛的方式 - 但在大多数情况下我不建议 - 将takeUntil完全放在顶级流上,然后只要repeat取消就重新启动史诗.因此,当我们取消时,这将关闭所有内容; 任何未决的ajaxs和任何未决的debounces.
export const apiValidate = action$ => {
return action$.ofType(validateRequestAction)
.debounceTime(250)
.switchMap((action) => (
Observable.ajax({
url: url,
method: 'GET',
crossDomain: true,
headers: {
"Content-Type": 'application/json'
},
responseType: 'json'
})
.map(payload => (new APISuccessValidate()))
.catch(payload => ([new APIFailureValidate()]))
))
.takeUntil(action$.ofType(validateCancelAction))
.repeat();
};
Run Code Online (Sandbox Code Playgroud)
值得注意的是,我使用术语epic和restart来帮助概念化我们的特定域,但这通常只是普通的RxJS,所以它通常适用于redux-observable之外."史诗"只是我们的一个函数模式的一个词,它接受一系列动作(输入)并返回一个动作流(输出).