Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to start/stop/resume a redux-observable epic by emitting actions?

This question may be about redux-observable or rxjs or both.

I'm looking for a way to start, stop or resume an epic through specific actions. For example, the epic (that's already part of the epic middelware) will be active when the action {type: 'START'} is received but will be inactive when the action {type: 'END'} is received. Is this possible?

like image 949
Huy Nguyen Avatar asked Aug 06 '17 03:08

Huy Nguyen


People also ask

What is an epic in Redux observable?

The concept of an epic is the core part of Redux-Observable. An epic is a function that takes a stream of actions and returns a stream of actions. All of the dispatched actions go into the action stream.

How do epic reducers work in Redux?

REMEMBER: Epics run alongside the normal Redux dispatch channel, after the reducers have already received them. When you map an action to another one, you are not preventing the original action from reaching the reducers; that action has already been through them! The real power comes when you need to do something asynchronous.

How do epics work in RxJS?

Remember, Epics take a stream of actions in and return a stream of actions out. If the RxJS operators and behavior shown so far is unfamiliar to you, you'll definitely want to take some time to dive deeper into RxJS before proceeding. You can then update your Store's state in response to that FETCH_USER_FULFILLED action:

What is the difference between Redux-thunk and an epic?

That way you can remain productive and learn RxJS as you go. redux-thunk is much simpler to learn and use, but that also means it's far less powerful. Of course, if you already love Rx like we do, you will probably use it for everything! An Epic is the core primitive of redux-observable.


1 Answers

You could use a combination of switchMap and filter to do this (assuming that all actions incl. the start/end-actions come from the same source)

If you start/end-actions are coming from a seperate source it is even easier, then you can skip the step of separating the source-stream.

Run the code-example below to see it in action.

// this would be your source
const actions$ = new Rx.Subject();

// in this example controllActions and dataActions are derived from the same stream,
// if you have the chance to use 2 seperate channels from the start, do that
const controllActions$ = actions$
  .filter(action => action.type === "END" || action.type === "START");
const dataActions$ = actions$
  .filter(action => action.type !== "END" && action.type !== "START");

const epic$ = controllActions$
  .switchMap(action => {
    if (action.type === "END") {
      console.info("Pausing stream");
      return Rx.Observable.never();
    } else {
      console.info("Starting/Resuming stream");
      return dataActions$;
    }
  });
epic$.subscribe(console.log);

// simulating some action emissions, the code below is _not_ relevant for the actual implementation
Rx.Observable.from([
  "Some data, that will not be emitted...",
  {type: "START"},
  "Some data, that _will_ be emitted...",
  "Some more data, that _will_ be emitted...",
  {type: "END"},
  "Some data, that will not be emitted...",
  "Some data, that will not be emitted...",
  {type: "START"},
  "Some data, that _will_ be emitted...",
  "Some more data, that _will_ be emitted..."
])
  .concatMap(d => Rx.Observable.of(d).delay(400))
  .subscribe(actions$);
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>
like image 97
olsn Avatar answered Oct 18 '22 19:10

olsn