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

时间:2017-06-26 15:42:52

标签: javascript rxjs rxjs5 redux-observable

我正在努力做一个"复杂的警报系统"在redux + redux-observable中。

要求是:

  • 操作应该请求警报: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方法来实现它?

1 个答案:

答案 0 :(得分:0)

对我而言,您似乎只想取消"取消"每当用户点击时,您的延迟观察结果就会被延迟观察,而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$);
        });
};

现在嵌套的observable产生一个DISMISS_ALERT动作,如果用户在maxDelay间隔过去之前点击,则不产生任何动作。