6

Redux-Saga でデバウンスする方法はありますか?後続の呼び出しが同じ遅延の後ろにキューに入れられ、キューに追加された新しいタスクごとにぶつかり続けます。lodash の debounce https://lodash.com/docs#debounceに似ています。

私は現在、redux-saga のデバウンスに似たものを持っていますが、各タスクを実行したいのでキャンセル部分を削除しました。後で単一のスレッドで発生するすべてのイベントをまとめたいだけです。

私が現在持っているもの:

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);
  }
}

フォークを変数に割り当ててから、それが実行されているかどうかを確認しようとしました (.isRunning()) が、そのフォークを別の遅延で延期する方法がわかりませんでした。

4

6 に答える 6

16

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)
}
于 2019-05-01T09:51:50.973 に答える
2

配列をキューとして使用してアクションをバッファに格納し、 setTimeout を使用してそれぞれで call() を呼び出してキューをフラッシュする例を書こうとしていました (その後、新しいアクションが前に入ってきた場合はそれに応じてタイムアウトをキャンセルします)有効期限が切れます)、しかし、redux-saga が Channels をサポートするようになったことに気付きました:

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

また、サガがビジー状態のときにアクションを格納するための組み込みバッファーもあります。ここでの秘訣は、ドキュメントの例からの API 呼び出しを関数に置き換えることdelayです。これにより、サガが「ビジー」になり、アクションがバッファリングされます。

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);
  }
}

また、さまざまなバッファー戦略から選択できます。

以前にチャネルを使用したことがないため、私の例があなたのケースで機能するかどうかは100%確信が持てませんが、問題に適応できることを願っています.

于 2016-05-23T18:32:55.850 に答える
1

takeLatest両方を使用して使用できますがdelay、機能するはずです

于 2019-03-27T16:27:26.173 に答える