Queuing and undoing events using idiomatic reduction

For example, the download manager. There can be any number of active downloads.

Actions can be sent to start, stop, end tagging, and mark the progress of a download for any particular download.

const START_DOWNLOAD = "START_DOWNLOAD";
const startDownload = payload => ({ type: START_DOWNLOAD, payload });

const DOWNLOAD_PROGRESS = "DOWNLOAD_PROGRESS";
const downloadProgress = payload => ({ type: DOWNLOAD_PROGRESS, payload });

const STOP_DOWNLOAD = "STOP_DOWNLOAD";
const stopDownload = payload => ({ type: STOP_DOWNLOAD, payload });

const COMPLETE_DOWNLOAD = "COMPLETE_DOWNLOAD";
const completeDownload = payload => ({ type: COMPLETE_DOWNLOAD payload });

These actions will contain an identifier to identify the load and can change the state of the reduction using the following reducer:

const downloadReducer = (state = initialState, action) => {
  switch (action.type) {
    case STOP_DOWNLOAD:
      return {
        ...state,
        [action.payload.id]: {
          state: "IDLE",
        },
      };

    case START_DOWNLOAD:
      return {
        ...state,
        [action.payload.id]: {
          state: "IN_PROGRESS",
          progress: 0,
        },
      };

    case DOWNLOAD_PROGRESS:
      return {
        ...state,
        [action.payload.id]: {
          state: "IN_PROGRESS",
          progress: action.payload.progress,
        },
      };

    case COMPLETE_DOWNLOAD:
      return {
        ...state,
        [action.payload.id]: {
          state: "DONE",
          progress: 100,
        },
      };

    default:
      return state;
  }
};

Now the question is how to control the asynchronous dispatch of these actions using the abbreviated observable.

For example, we could do something like this:

const downloadEpic = action$ =>
  action$.ofType(START_DOWNLOAD).mergeMap(action =>
    downloader
    .takeUntil(
      action$.filter(
        stop =>
        stop.type === STOP_DOWNLOAD &&
        stop.payload.id === action.payload.id,
      ),
    )
    .map(progress => {
      if (progress === 100) {
        return completeDownload({
          id: action.payload.id
        });
      } else {
        return downloadProgress({
          id: action.payload.id,
          progress
        });
      }
    }),
  );

. , , . mergeMap concatMap, . mergeMap , .

, .

, .

rxjs redux, ?

+6
1

, , , . tl; dr, , , :)


, , , . ATTEMPT_DOWNLOAD. , >= max, , , , .

, . .

{ active: ['123', '456', ...etc], queued: ['789'] }

/ , active.length, queued.length

, - , , , . , . DEQUEUE_DOWNLOAD - .

, active, queued , . , , , , , , .


, :

  • , , , , (, " " - )
  • . , , ,
  • , .
  • , , , . . , , START_DOWNLOAD

, -. / ? . .

, . ( ), . !

+2

All Articles