如何从 Redux Toolkit 去抖动 createAsyncThunk

How to debounce createAsyncThunk from Redux Toolkit

我正在从 Redux 迁移到 Redux Toolkit。我这里的简化代码是使用 lodash/debounce.

进行去抖动更新
import debounce from "lodash/debounce";

const updateApplication = async (app, dispatch) => {
const state = getState();

try {
  const result = await update(app);
  dispatch({
    type: UPDATE,
    result: result
  });
    } catch (err) {
    console.log(err);
    }
  };

export default debounce(updateThunk, 2000);

问题是当我转到 createAsyncThunk 时它没有被执行。


const updateApp = createAction("app/update");
const updateApplication = createAsyncThunk(
  "app/updateDebounced",
  async (app, { dispatch }) => {
   
    try {
      const result = await update(app);
          dispatch(updateApp(result))
        );
      }
    } catch (err) {
      // console.log(err);
    }
  }
);

export default debounce(updateApplication, 2000)

如何让它发挥作用?

const updateApp = createAction("app/update");
const handler = async (app, { dispatch }) => {
    try {
      const result = await update(app);
          dispatch(updateApp(result))
        );
      }
    } catch (err) {
      // console.log(err);
    }
  }
const debouncedHandler = debounce(handler, 2000);

export default createAsyncThunk(
  "app/updateDebounced",
  debouncedHandler
);

A debounced analogue of createAsyncThunk from @reduxjs/toolkit

import { createAsyncThunk } from '@reduxjs/toolkit';

/**
 * A debounced analogue of the `createAsyncThunk` from `@reduxjs/toolkit`
 * @param {string} typePrefix - a string action type value
 * @param payloadCreator - a callback function that should return a promise containing the result
 *   of some asynchronous logic
 * @param {number} wait - the number of milliseconds to delay.
 * @param {Object} [options] - the options object
 * @param {number} [options.maxWait = 0] - The maximum time `payloadCreator` is allowed to be
 * delayed before it's invoked.
 * @param {boolean} [options.leading = false] - Specify invoking on the leading edge of the timeout.
 */
const createDebouncedAsyncThunk = (typePrefix, payloadCreator, wait, options) => {
  const { maxWait = 0, leading = false } = options ?? {};
  let timer = 0;
  let maxTimer = 0;
  let resolve;
  const invoke = () => {
    clearTimeout(maxTimer);
    maxTimer = 0;
    if (resolve) {
      resolve(true);
      resolve = undefined;
    }
  };
  const cancel = () => {
    if (resolve) {
      resolve(false);
      resolve = undefined;
    }
  };
  return createAsyncThunk(typePrefix, payloadCreator, {
    condition() {
      const immediate = leading && !timer;
      clearTimeout(timer);
      timer = setTimeout(() => {
        invoke();
        timer = 0;
      }, wait);
      if (immediate) return true;
      cancel();
      if (maxWait && !maxTimer) maxTimer = setTimeout(invoke, maxWait);
      return new Promise(res => {
        resolve = res;
      });
    },
  });
};

export default createDebouncedAsyncThunk;