一个复杂的警报系统 Redux-observable。不在史诗结束时派遣行动
A complex alert system Redux-observable. not dispatch action at the end of an epic
我正在尝试在 redux + redux-observable 中做一个 "complexe alert system"。
要求是:
- 一个动作应该请求警报:REQUEST_ALERT
- 一个动作应该创建警报 + 添加一个 id:SET_ALERT(在史诗中完成)
- 警报应在 3 秒后关闭:DISMISS_ALERT(在史诗中完成)
- 用户单击可以关闭警报:DISMISS_ALERT
(我们可以重构直接使用 SET_ALERT 而不是 REQUEST_ALERT 直接在 reducer 内部,但这不是这里的问题)
我几乎实现了我的目标:
// generate the alert from the request
// you can ignore it if refactor with only REQUEST_ALERT
export const generateAlert$ = (action$) => {
return action$.ofType(REQUEST_ALERT)
.map(action => ({
type: SET_ALERT,
payload: generateAlertPayload(),
// just create action de type SET_ALERT and add an id
})
)
}
// the real important part
export const timeoutDismissAlert$ = (action$) => {
return action$.ofType(SET_ALERT)
.mergeMap(action =>
Rx.Observable.empty()
.concat(
// I wait for max delay and send the payload dismiss_alert
Rx.Observable.of(action)
.delay(maxDelay)
.map(({payload}) => ({type: DISMISS_ALERT, payload: payload.id}))
// I make a race with the user click vs the delay
.race(
action$.ofType(DISMISS_ALERT)
.skipWhile(({payload}) => payload !== action.payload.id)
.first()
.map(() => null)
)
)
// I would like to dispatch an action only if the delay win
.map((a) => a ? a : {type: "I_DONT_WANT"})
)
}
有没有办法在史诗结束时不发送动作?或者更好的 Rxjs 方法来实现它?
对我来说,您似乎只想 "cancel" 在用户点击时延迟观察,takeUntil
可以提供帮助。
我想象想要的史诗看起来像这样:
// action creator
const dismissAlert = payload => ({ type: DISMISS_ALERT, payload });
// epic
const dismissAlert$ = action$ => {
return action$.ofType(SET_ALERT)
.mergeMap(action => {
const dismiss$ = action$.ofType(DISMISS_ALERT)
.filter(({ payload }) => payload === action.payload.id);
// the interesting part
return Rx.Observable.timer(maxDelay)
.mapTo(dismissAlert(action.payload.id))
.takeUntil(dismiss$);
});
};
现在,如果用户在 maxDelay
时间间隔过去之前点击,嵌套的 observable 要么产生单个 DISMISS_ALERT 动作,要么什么都不产生。
我正在尝试在 redux + redux-observable 中做一个 "complexe alert system"。
要求是:
- 一个动作应该请求警报:REQUEST_ALERT
- 一个动作应该创建警报 + 添加一个 id:SET_ALERT(在史诗中完成)
- 警报应在 3 秒后关闭:DISMISS_ALERT(在史诗中完成)
- 用户单击可以关闭警报:DISMISS_ALERT
(我们可以重构直接使用 SET_ALERT 而不是 REQUEST_ALERT 直接在 reducer 内部,但这不是这里的问题)
我几乎实现了我的目标:
// generate the alert from the request
// you can ignore it if refactor with only REQUEST_ALERT
export const generateAlert$ = (action$) => {
return action$.ofType(REQUEST_ALERT)
.map(action => ({
type: SET_ALERT,
payload: generateAlertPayload(),
// just create action de type SET_ALERT and add an id
})
)
}
// the real important part
export const timeoutDismissAlert$ = (action$) => {
return action$.ofType(SET_ALERT)
.mergeMap(action =>
Rx.Observable.empty()
.concat(
// I wait for max delay and send the payload dismiss_alert
Rx.Observable.of(action)
.delay(maxDelay)
.map(({payload}) => ({type: DISMISS_ALERT, payload: payload.id}))
// I make a race with the user click vs the delay
.race(
action$.ofType(DISMISS_ALERT)
.skipWhile(({payload}) => payload !== action.payload.id)
.first()
.map(() => null)
)
)
// I would like to dispatch an action only if the delay win
.map((a) => a ? a : {type: "I_DONT_WANT"})
)
}
有没有办法在史诗结束时不发送动作?或者更好的 Rxjs 方法来实现它?
对我来说,您似乎只想 "cancel" 在用户点击时延迟观察,takeUntil
可以提供帮助。
我想象想要的史诗看起来像这样:
// action creator
const dismissAlert = payload => ({ type: DISMISS_ALERT, payload });
// epic
const dismissAlert$ = action$ => {
return action$.ofType(SET_ALERT)
.mergeMap(action => {
const dismiss$ = action$.ofType(DISMISS_ALERT)
.filter(({ payload }) => payload === action.payload.id);
// the interesting part
return Rx.Observable.timer(maxDelay)
.mapTo(dismissAlert(action.payload.id))
.takeUntil(dismiss$);
});
};
现在,如果用户在 maxDelay
时间间隔过去之前点击,嵌套的 observable 要么产生单个 DISMISS_ALERT 动作,要么什么都不产生。