Redux saga debounce 而不仅仅是延迟/取消

Lab*_*tis 6 javascript generator reactjs redux redux-saga

有没有办法在 Redux-Saga 中去抖动,其中后续调用在相同的延迟之后排队,这会不断被添加到队列中的每个新任务所影响。类似于 lodash 的 debounce https://lodash.com/docs#debounce

我目前有一些类似于 redux-saga 的 debounce 的东西,但删除了取消部分,因为我仍然想对每个任务采取行动,我只想将所有事件捆绑在一起,以便稍后在单个线程中触发。

我目前拥有的:

const deferTime = 2000;
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

export function* sendClickEvent (event, debounce) {
  if (debounce) {
    yield call(delay, deferTime);
  }
  yield put(action(event));
}

export function* clickSaga () {
  while (true) {
    const action = yield take(WIDGET_CLICKED);
    const state = yield select();
    const debounce = action.meta && action.meta.debounce;
    const payload = getWidgetClickPayload(state, action);
    const defaultData = getDefaultData(state);
    const event = {
      name: payload.name,
      data: Object.assign(defaultData, payload.data)
    };
    yield fork(sendClickEvent, event, debounce);
  }
}
Run Code Online (Sandbox Code Playgroud)

我尝试将 fork 分配给变量,然后检查它是否正在运行 (.isRunning()),但不知道如何再延迟一次该 fork。

Dom*_*nic 14

Redux saga 现在具有去抖动功能/效果:

import { call, put, debounce } from `redux-saga/effects`

function* fetchAutocomplete(action) {
  const autocompleteProposals = yield call(Api.fetchAutocomplete, action.text)
  yield put({type: 'FETCHED_AUTOCOMPLETE_PROPOSALS', proposals: autocompleteProposals})
}

function* debounceAutocomplete() {
  yield debounce(1000, 'FETCH_AUTOCOMPLETE', fetchAutocomplete)
}
Run Code Online (Sandbox Code Playgroud)

  • 那么,你在哪里调用 `debounceAutocomplete` 呢? (3认同)

fab*_*tto 3

我打算编写一个示例,使用数组作为队列来存储要缓冲的操作,并使用 setTimeout 来刷新每个队列上调用 call() 的队列(然后,如果之前有新操作进入,则相应地取消超时它过期了),但我注意到现在 redux-saga 支持 Channels:

https://yelouafi.github.io/redux-saga/docs/advanced/Channels.html

它们还有一个内置缓冲区,用于在传奇繁忙时存储操作。这里的技巧是将文档示例中的 api 调用替换为您的delay函数,以便 saga 处于“繁忙”状态并为您缓冲操作。

const deferTime = 2000;
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

export function* sendClickEvent (event) {
  yield put(action(event));
}

export function* clickSaga () {
  // Create a channel (buffered by default)
  const requestChan = yield actionChannel(WIDGET_CLICKED)

  while (true) {
    // Note: we now take actions from the channel (buffered)
    const action = yield take(requestChan) 

    const state = yield select();
    const debounce = action.meta && action.meta.debounce;
    const payload = getWidgetClickPayload(state, action);
    const defaultData = getDefaultData(state);
    const event = {
      name: payload.name,
      data: Object.assign(defaultData, payload.data)
    };
    // This should "suspends" the saga and makes it buffer events.
    yield call(delay, deferTime)

    yield fork(sendClickEvent, event);
  }
}
Run Code Online (Sandbox Code Playgroud)

您还可以选择不同的缓冲策略。

请注意,我不能 100% 确定我的示例适用于您的情况,因为我以前从未使用过通道,但希望您可以根据您的问题进行调整。