Redux sagas Fetch only once when same id is dispatched multiple times

拜拜、爱过 提交于 2019-12-06 15:37:20

This is how I solved this problem in another saga. The "type" here can be ignored

  • Accumulate the requested id in an ids object:
  • Dispatch action to fetch all accumulated ids
  • Debounce fetch for 50 milliseconds
  • While waiting... Add new Ids to the ids object
  • While waiting... Cancel fetch task to give you 50 new milliseconds
  • Commit fetch
  • Clear tasks and ids

Code:

let ids = {};
let tasks = {};

function* watchCounterRequests() {
  yield takeEvery(actionTypes.COUNTER_REQUESTED, accumulate);
}

function* watchCounterFetchRequests() {
  yield takeEvery(actionTypes.COUNTER_FETCH_REQUESTED, counterFetchRequested);
}

function* accumulate(action) {
  const {id, type} = action.payload;
  if (!ids[type]) ids[type] = {};

  ids[type][id] = true;
  if (tasks[type]) {
    yield cancel(tasks[type]);
  }
  tasks[type] = yield fork(fetchCounters, type);
}

function* fetchCounters(type) {
  yield call(delay, 50);

  yield put({
    type: actionTypes.COUNTER_FETCH_REQUESTED,
    payload: {type: type, ids: Object.keys(ids[type])},
  });

  delete ids[type];
  delete tasks[type];
}

function* counterFetchRequested(action) {
  const {ids, type} = action.payload;
  let typeName = type + 'Ids';
  let req = {
    [typeName]: ids
  };
  yield put(counterActions.loadCounters(req));
}

export default [watchCounterRequests, watchCounterFetchRequests];

Most of this comes from here: https://marmelab.com/blog/2016/10/18/using-redux-saga-to-deduplicate-and-group-actions.html

It think you are looking for something like

import {
 take,
 fork,
 cancel,
} from 'redux-saga';

const takeLatestDeep = (pattern, identifier, fn, ...args) => fork(function* () {
  const tasks = {};

  while(true) {
    const action = yield take(pattern);
    const id = identifier(action);

    if (tasks[id]) {
      yield cancel(tasks[id]);
    } 

    tasks[id] = yield fork(fn, ...args.concat(action));
  }
}

That you can use like this

yield takeLatestDeep(
   actionTypes.USER_REQUESTED,
   action => action.payload.id,
   fetchLegacyRecipientsSaga,
   ...args 
);
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!