Redux Observable throttle Ajax 仅请求满足某些条件
Redux Observable throttle Ajax requests only some conditions met
在我的 reactjs
redux
应用程序中,我使用 redux observable epics
中间件来处理 ajax 请求以取消一些请求。
const epicRequest = $actions => {
return $actions
.ofType(MY_ACTION_TYPE)
.debounceTime(500)
.switchMap( action =>{
// Doing Ajax
})
}
我的问题是我在按下某些按钮时调用了这个动作,我有两种按钮都可以调用相同的动作,在这种情况下,如果第一个动作和第二个动作的调用是不同的按钮,我不想要去抖动,我只想在动作来自同一个按钮时去抖动。
要解决此问题,您必须从按钮调用中传递额外的道具,并检查史诗中的道具。
在您的组件按钮点击调用中,传递您的按钮标识。
onclick = () => {
// assume arg name is 'from'
this.props.yourAction('a') // can be 'a'/'b' ...
}
在您的操作调用中,传递您从按钮调用中获得的值。
const yourAction = (from) => {
return { type: MY_ACTION_TYPE, from }
}
在减速器开关盒中
case MY_ACTION_TYPE:
return {...state, from:action.from}
最后,在你的 epic 中间件函数中,将 .debounceTime(600)
替换为 .debounce()
,with this 你可以将函数作为参数传递给 returns Observable.timer()
。所以你可以在这里检查你的道具和 return 去抖动时间。
let from = null
const epicRequest = $actions => {
return $actions
.ofType(MY_ACTION_TYPE)
//.debounceTime(500)
.debounce((action) => {
// check button type is not yet set or not previous type
const timer = !from || (from !== action.from) ? Observable.timer(0) : Observable.timer(600)
// update button type
from = (from !== action.from) ? action.from : from
// return Observable.timer()
return timer
})
.switchMap( action =>{
// Do your Ajax
})
}
不清楚您的意思是希望它们都去抖动,但独立地,或者您只希望其中一个去抖动。我已经包含了两个问题的答案:
2+ 个按钮独立去抖动
我高度建议让他们发出不同的动作类型,如果他们有不同的意图。如果意图相同,例如相同的按钮在列表项中重复,那么处理此问题的一种方法是使用 groupBy
通过按钮始终包含的一些唯一键独立地对每个按钮进行分组。
const epicRequest = action$ =>
action$
.ofType(MY_ACTION_TYPE)
.groupBy(action => action.somethingUnique)
.mergeMap(action$ =>
action$
.debounceTime(500)
.switchMap(action => {
// Doing Ajax
})
);
此示例假定每个按钮都包含唯一标识它的内容,包括为 somethingUnique
。
groupBy
上的一些资源
WARNING: by default groupBy
never complete()'s or otherwise cleans up every group Observable it creates, which means this potentially is a memory leak. Whether that matters in your app or not, only you can know. If it does, groupBy
supports a third argument duration selector that you can use to decide when to stop tracking a particular group--that doesn't mean it create a new one if its needed later, just that the current Observable representing it is complete()'d. Often this is tough to do cleanly in practice without some sort of explicit teardown signal, like a route navigation action away from the page.
See the docs for more info: http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-groupBy
durationSelector: function(grouped: GroupedObservable<K, R>): Observable<any>
1 个按钮去抖动,另一个按钮从不去抖动
这意味着他们有不同的意图。一个打算去抖动,另一个不打算去抖动,即使在去抖动之后它们的动作是相同的。
需要去抖动的动作可以像MY_ACTION_TYPE_DEBOUNCED
一样发出完全不同的动作,然后在去抖动后发出正常的MY_ACTION_TYPE
const myActionTypeDebouncedEpic = action$ =>
action$
.ofType(MY_ACTION_TYPE_DEBOUNCED)
.debounceTime(500)
.map(action => ({
...action,
type: MY_ACTION_TYPE
}));
const myActionTypeEpic = action$ =>
action$
.ofType(MY_ACTION_TYPE)
.switchMap(action => {
// Doing Ajax
});
在我的 reactjs
redux
应用程序中,我使用 redux observable epics
中间件来处理 ajax 请求以取消一些请求。
const epicRequest = $actions => {
return $actions
.ofType(MY_ACTION_TYPE)
.debounceTime(500)
.switchMap( action =>{
// Doing Ajax
})
}
我的问题是我在按下某些按钮时调用了这个动作,我有两种按钮都可以调用相同的动作,在这种情况下,如果第一个动作和第二个动作的调用是不同的按钮,我不想要去抖动,我只想在动作来自同一个按钮时去抖动。
要解决此问题,您必须从按钮调用中传递额外的道具,并检查史诗中的道具。
在您的组件按钮点击调用中,传递您的按钮标识。
onclick = () => {
// assume arg name is 'from'
this.props.yourAction('a') // can be 'a'/'b' ...
}
在您的操作调用中,传递您从按钮调用中获得的值。
const yourAction = (from) => {
return { type: MY_ACTION_TYPE, from }
}
在减速器开关盒中
case MY_ACTION_TYPE:
return {...state, from:action.from}
最后,在你的 epic 中间件函数中,将 .debounceTime(600)
替换为 .debounce()
,with this 你可以将函数作为参数传递给 returns Observable.timer()
。所以你可以在这里检查你的道具和 return 去抖动时间。
let from = null
const epicRequest = $actions => {
return $actions
.ofType(MY_ACTION_TYPE)
//.debounceTime(500)
.debounce((action) => {
// check button type is not yet set or not previous type
const timer = !from || (from !== action.from) ? Observable.timer(0) : Observable.timer(600)
// update button type
from = (from !== action.from) ? action.from : from
// return Observable.timer()
return timer
})
.switchMap( action =>{
// Do your Ajax
})
}
不清楚您的意思是希望它们都去抖动,但独立地,或者您只希望其中一个去抖动。我已经包含了两个问题的答案:
2+ 个按钮独立去抖动
我高度建议让他们发出不同的动作类型,如果他们有不同的意图。如果意图相同,例如相同的按钮在列表项中重复,那么处理此问题的一种方法是使用 groupBy
通过按钮始终包含的一些唯一键独立地对每个按钮进行分组。
const epicRequest = action$ =>
action$
.ofType(MY_ACTION_TYPE)
.groupBy(action => action.somethingUnique)
.mergeMap(action$ =>
action$
.debounceTime(500)
.switchMap(action => {
// Doing Ajax
})
);
此示例假定每个按钮都包含唯一标识它的内容,包括为 somethingUnique
。
groupBy
WARNING: by default
groupBy
never complete()'s or otherwise cleans up every group Observable it creates, which means this potentially is a memory leak. Whether that matters in your app or not, only you can know. If it does,groupBy
supports a third argument duration selector that you can use to decide when to stop tracking a particular group--that doesn't mean it create a new one if its needed later, just that the current Observable representing it is complete()'d. Often this is tough to do cleanly in practice without some sort of explicit teardown signal, like a route navigation action away from the page. See the docs for more info: http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-groupBydurationSelector: function(grouped: GroupedObservable<K, R>): Observable<any>
1 个按钮去抖动,另一个按钮从不去抖动
这意味着他们有不同的意图。一个打算去抖动,另一个不打算去抖动,即使在去抖动之后它们的动作是相同的。
需要去抖动的动作可以像MY_ACTION_TYPE_DEBOUNCED
一样发出完全不同的动作,然后在去抖动后发出正常的MY_ACTION_TYPE
const myActionTypeDebouncedEpic = action$ =>
action$
.ofType(MY_ACTION_TYPE_DEBOUNCED)
.debounceTime(500)
.map(action => ({
...action,
type: MY_ACTION_TYPE
}));
const myActionTypeEpic = action$ =>
action$
.ofType(MY_ACTION_TYPE)
.switchMap(action => {
// Doing Ajax
});