1
votes

After dispatching SEARCH, I'm trying to cancel an AJAX request but also to keep the observable listening. I'm using takeUntil and waiting for an action of type CLEAR_SEARCH_RESULTS to cancel the request.

Here's my epic:

const searchEpic = action$ =>
    action$.ofType(SEARCH).pipe(
        debounceTime(500),
        switchMap(({ payload }) =>
            search(query).pipe(
                map(({ response }) => SearchActions.searchSuccess(response)),  // dispatches SEARCH_SUCCESS
                takeUntil(
                    action$.ofType(CLEAR_SEARCH_RESULTS)
                )
            )
        )
    )

Edit: I have a Redux logger which outputs dispatched actions in the following order:

  1. SEARCH
  2. SEARCH
  3. SEARCH
  4. SEARCH
  5. CLEAR_SEARCH_RESULTS
  6. SEARCH_SUCCESS

(each SEARCH is a keystroke)

1
So where's the problem? Any errors? What you have now looks fine. How you know it's not canceled or it doesn't simply come after the request is done.martin
I've edited my post, please have a lookEyal C
What you have look fine so the problem is probably somewhere else. Otherwise make a demo reproducing the problem.martin
Hey @martin, sorry for the late response. Here's a repo with a demo: github.com/eyal0803/job-searchEyal C

1 Answers

1
votes

I solved it by moving the takeUntil outside of the switchMap and putting a repeat() after it, like so:

const searchEpic = action$ =>
    action$.ofType(SEARCH).pipe(
        debounceTime(500),
        switchMap(({ payload }) =>
            search(query).pipe(
                map(({ response }) => SearchActions.searchSuccess(response))
            )
        ),
        takeUntil(action$.ofType(CLEAR_SEARCH_RESULTS)),
        repeat()
    )

The problem was that the epic starts listening for CLEAR_SEARCH_RESULTS only after the 500ms of the debounceTime, which is not what I wanted.

All credit goes to this answer by Jay Phelps and to Evert Bouw for finding and pointing it out to me on Gitter.