rxjs throttle fetch until request has finished

若如初见. 提交于 2020-01-05 03:43:25

问题


I have an Observable that makes a request that gives back some information that is different each time. This observable is called by a user clicking a button. I want to prevent the user from clicking this button before the request has returned with information, and once it has returned, allow the user to click for an update once again.

This is the request without stopping the user at any point.

const fetchRepos = () =>
  fetch( 'https://api.github.com/search/repositories?q=+language:javascript&sort=updated&order=desc')
    .then(response => response.json())

export function fetchReposEpic(action$: any) {
  return action$.ofType(FETCH_POPULAR_REPOS_REQUEST)
    .switchMap(fetchRepos)
    .map(data => ({
      type: FETCH_POPULAR_REPOS_SUCCESS,
      payload: data.items
    }))
}

One solution is to throttle the user for 500 milliseconds after the Observable begins

export function fetchReposEpic(action$: any) {
  return action$.ofType(FETCH_POPULAR_REPOS_REQUEST)
    .throttleTime(500)
    .switchMap(fetchRepos)
    .map(data => ({
      type: FETCH_POPULAR_REPOS_SUCCESS,
      payload: data.items
    }))
}

The problem here is I am only estimating how long the request might take, worse still, if the request finishes before this time, the user could click the button and the click would be ignored.

The closest to a solution I have is passing the fetch promise to throttle.

export function fetchReposEpic(action$: any) {
  return action$.ofType(FETCH_POPULAR_REPOS_REQUEST)
    .throttle(fetchRepos)
    .map(data => ({
      type: FETCH_POPULAR_REPOS_SUCCESS,
      payload: []
    }))
}

This will wait until the request has finished and will throttle all other actions until then. The problem is that I do not know how to get the returned value of throttle. All throttle examples I could find also show the returned value of throttle being thrown away.

So to summarize, I want a way to wait until the observable has completed before firing it off again.


回答1:


The solution is for your UI to disable the button based on some state in redux, like isFetchingRepos and your reducers will flip this to true when FETCH_POPULAR_REPOS_REQUEST is received and false when FETCH_POPULAR_REPOS_SUCCESS is.

If you later add error handling, make sure you also flip it back to false when an error action is seen.

The ping/pong example in the docs is actually mostly the same thing https://redux-observable.js.org/docs/basics/Epics.html#a-basic-example. How you structure/store that state in your store is up to you--for more complex cases where ID's are involved and concurrent requests can happen, you'll want to make sure that state is per request (or ID if using switchMap)



来源:https://stackoverflow.com/questions/44667352/rxjs-throttle-fetch-until-request-has-finished

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!