首页 > 解决方案 > 在不同的动作上使用 takeLatest 来限制相同的传奇/史诗动作

问题描述

我是 redux-saga/observable 的新手。但我无法处理看起来非常适合这些的场景。所以; 如果表单发生任何更改,我想调用 API。但由于性能原因,我不想大量调用 API。

基本上,当我触发 SLIDERCHANGED、TEXTBOXCHANGED、CHECKBOXCHECKED 时,我还想调用 getData 函数。但我需要延迟检查其他操作。例如; 如果 SLIDERCHANGED 被触发,它应该等待 1sn,如果此时触发 TEXTBOXCHANGED,它将被取消并等待 1sn 更多调用 getData 函数。所以这就是我尝试实现 Redux-saga 或 redux-observable 的原因。

我有动作类型;

const SLIDERCHANGED = 'APP/sliderchanged';
const TEXTBOXCHANGED = 'APP/textboxchanged';
const CHECKBOXCHECKED = 'APP/checkboxchecked';
const LOADING = 'APP/loading';
const LOADDATA = 'APP/loaddata';
const ERRORLOADDATA = 'APP/errorloaddata';

我也有行动;

export function updateSliderValue(val) {
  return { type: SLIDERCHANGED, val };
}

export function updateTextboxValue(val) {
  return { type: TEXTBOXCHANGED, val };
}

export function updateCheckboxValue(val) {
  return { type: CHECKBOXCHECKED, val };
}

export function loading() {
  return { type: LOADING };
}

export function loadData(data) {
  return { type: LOADDATA, data };
}

export function errorLoadData(err) {
  return { type: ERRORLOADDATA, err };
}

export function getData(vehicleInfo) { // redux-thunk ASYNC function
  return (dispatch, getState) => {
    dispatch(loading());

      return dispatch(apiCall('/getAllData', {}))
        .then(payload => {
          dispatch(loaddata(payload));
        })
        .catch(error => {
          dispatch(errorLoadData(error));
        });
  };
}

使用 redux-saga,我做到了,但它不起作用。它以 1sn 延迟在每次更改时调用 getData 函数。

import { put, throttle } from 'redux-saga/effects';
import {
  SLIDERCHANGED,
  TEXTBOXCHANGED,
  CHECKBOXCHECKED
} from './constants';
import { getData } from './actions';


function* onFormUpdate() {
  yield put(getData());
}

export function* watchFormChange() {
  yield throttle(
    10000,
    [SLIDERCHANGED, TEXTBOXCHANGED, CHECKBOXCHECKED],
    onFormUpdate
  );
}

使用 redux-observable,不知何故我也得到了同样的错误。

import { ofType } from 'redux-observable';
import { delay, map, debounceTime } from 'rxjs/operators';
import {
  SLIDERCHANGED,
  TEXTBOXCHANGED,
  CHECKBOXCHECKED
} from './constants';
import { getData } from './actions';

export const onFormUpdate = action => {
  return action.pipe(
    ofType(SLIDERCHANGED, TEXTBOXCHANGED, CHECKBOXCHECKED),
    debounceTime(1000),
    map(() => getData())
  );
};

有没有人有任何想法或意见来实现这一点?

标签: reduxredux-thunkredux-sagaredux-observable

解决方案


未经测试,我认为您可以编写如下解决方案:

import { delay } from 'redux-saga'
import { put } from 'redux-saga/effects'

function* onFormUpdate() {
  yield delay(1000)
  yield put(getData())
}

export function* watchFormChange() {
  yield takeLatest(
    [SLIDERCHANGED, TEXTBOXCHANGED, CHECKBOXCHECKED],
    onFormUpdate,
  )
}

这里的想法是,一旦三个动作中的另一个被调度,takeLatest它将立即取消。onFormUpdate所以 while onFormUpdateis indelay然后被取消,下一步,即put,将不再被调用。


推荐阅读