一个复杂的警报系统 Redux-observable。不在史诗结束时派遣行动

A complex alert system Redux-observable. not dispatch action at the end of an epic

我正在尝试在 redux + redux-observable 中做一个 "complexe alert system"。

要求是:

(我们可以重构直接使用 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 动作,要么什么都不产生。