首页 > 解决方案 > 如何使用 rxjs 表示法向动作触发器 react-redux 添加延迟

问题描述

我有一个由动作 sendSMS 触发的按钮,然后该动作触发效果 SendSMSEffect。在这种情况下,我想禁用 sendSms 按钮 5 秒,但是,setTimeout 似乎永远不会触发最后一个动作“setDisabled”

export const sendSMSEffect:
  Epic<IFluxPayloadAction<any, string>, any, IAppState>
  = (action$, state$) =>
  action$.pipe(
    ofType(SMSActions.SendSMS),
    map((action) => action.payload),
    map((payload) =>  {
      const mobile:string = getMobilePhoneFromPersonalDetails(state$.value);
      return {mobile, smsType:payload};
    }),
    switchMap((payload) => {
      const smsSelector = getSmsDetailsSelector(state$.value);
      const smsContent = retrieveSms(payload.smsType, smsSelector);

      return concat(
        of(showLoader(sms.sendingSMS)),
        from(sendSMSService(smsContent, payload.mobile, true)).pipe(
          switchMap((response:ISMSResponse) => {
            const wasSMSSent = response.Sent === 'Y' ? true : false;
            if (payload.smsType === smsType.Validation) {
              return concat(of(wasValidationSMSSent(wasSMSSent)), of(updateSMSValidationRetry()));

            })),
        ***of(setTimeout(() => setDisabled(false), 5000)),***
      of(hideLoader(sms.sendingSMS)),
    );
    }));

标签: reactjstypescriptreact-reduxrxjs

解决方案


尝试使用 rxjs 中的计时器运算符。

export const sendSMSEffect:
  Epic<IFluxPayloadAction<any, string>, any, IAppState>
  = (action$, state$) =>
  action$.pipe(
    ofType(SMSActions.SendSMS),
    map((action) => action.payload),
    map((payload) =>  {
      const mobile:string = getMobilePhoneFromPersonalDetails(state$.value);
      return {mobile, smsType:payload};
    }),
    switchMap((payload) => {
      const smsSelector = getSmsDetailsSelector(state$.value);
      const smsContent = retrieveSms(payload.smsType, smsSelector);

      return concat(
        of(showLoader(sms.sendingSMS)),
        from(sendSMSService(smsContent, payload.mobile, true)).pipe(
          switchMap((response:ISMSResponse) => {
            const wasSMSSent = response.Sent === 'Y' ? true : false;
            if (payload.smsType === smsType.Validation) {
              return concat(of(wasValidationSMSSent(wasSMSSent)), of(updateSMSValidationRetry()));

            })),
      timer(5000).pipe(take(1))subscribe(() => of(setDisabled(false)));    <------------ LIKE THIS
      of(hideLoader(sms.sendingSMS)),
    );
    }));

推荐阅读