Redux-Observable - 如果下一个请求与当前请求具有相同的参数,则取消下一个请求,但当它们不同时让它 运行
Redux-Observable - Cancel next request if it has same parameters with current one, but let it run when they are different
我是响应式编程的新手。只是想了解可观察对象和 rxjs 运算符。我有一个 react-redux
应用程序,它有一个自定义中间件来处理缓存数据和 isFetching
标志。虽然它只处理我需要的事情,但对于取消或去抖动之类的事情可能会很复杂。所以,我想将此应用程序迁移到 redux-observable
.
如果当前正在提取同一部电影,我不想提取它。我只是将 selectIsFetchingMovieById(action.movieId)
选择器传递给自定义中间件。如果它 returns true
,它不会将任何东西传递给 reducer。 But when the selector returns false
, it fetches the movie, 运行s through either .then
or .catch
like any regular promise based fetch data process.
但是当我使用 redux-observable
时,给定 movieId 的 isFetching
状态已经是 true
。因为 reducer 已经得到了 ({type: FETCH_MOVIE_REQUEST, movieId: "10" })
动作。选择器总是 returns true
.
如果我使用switchMap
,它会取消之前的请求,即使它有不同的movieId。 exhaustMap
不会 运行 下一个请求,即使它有不同的 movieId 等
现在我有了这部史诗。它适用于 cachedData
情况。如果商店已经有电影,则不会继续。但是isFetching
基于movieId还是有问题
const fetchMovieEpic = (action$, state$) =>
action$.pipe(
ofType(actionTypes.FETCH_MOVIE_REQUEST),
filter(action => {
const cachedData = selectors.selectMovie(state$.value, action.movieId);
return !verifyCachedData(cachedData, action.requiredFields);
}),
map(action => action.movieId),
switchMap(movieId =>
ajax.getJSON(`${BASE_API_URL}/movie/${movieId}?api_key=${api_key}`).pipe(
map(response => normalize(response, schemas.movieSchema)),
map(normalizedData => fetchMovieSuccess(movieId, normalizedData)),
catchError(() => of(fetchMovieError())),
takeUntil(
action$.pipe(
ofType("FETCH_MOVIE_CANCELLED"),
filter(action => action.movieId === movieId)
)
)
)
)
);
我如何使用 rxjs 运算符或任何其他技术来实现它?我不想添加像 FETCH_MOVIE_TOGGLE_LOADING
这样的额外 actionType。我已经有 REQUEST
、SUCCESS
、ERROR
和 CANCELLED
。还有很多其他的减速器和 epics。因此,使用运算符保持简单可能是一个不错的选择:)
谢谢!
根据定义 exhaustMap
假设可以工作。您可以通过重组流并简化内部流来调试它
exhaustMap(movieId =>ajax.getJSON(`${BASE_API_URL}/movie/${movieId}?api_key=${api_key}`).pipe(catchError(() => of(fetchMovieError()))
),
并查看后续操作是否会在请求完成后触发
我知道有点晚了,我实际上已经放弃使用 redux-observable。我无法用它编写我想要的代码。这让我觉得它不容易阅读。
坚持使用 redux-thunk 并在特殊情况下使用 redux-saga 可能要容易得多。至少对我来说是。
这是我在分组解决方案中使用的 epics 的最新版本:
https://gist.github.com/onderonur/e55f841188263fca5ddd111d218fd505
我是响应式编程的新手。只是想了解可观察对象和 rxjs 运算符。我有一个 react-redux
应用程序,它有一个自定义中间件来处理缓存数据和 isFetching
标志。虽然它只处理我需要的事情,但对于取消或去抖动之类的事情可能会很复杂。所以,我想将此应用程序迁移到 redux-observable
.
如果当前正在提取同一部电影,我不想提取它。我只是将 selectIsFetchingMovieById(action.movieId)
选择器传递给自定义中间件。如果它 returns true
,它不会将任何东西传递给 reducer。 But when the selector returns false
, it fetches the movie, 运行s through either .then
or .catch
like any regular promise based fetch data process.
但是当我使用 redux-observable
时,给定 movieId 的 isFetching
状态已经是 true
。因为 reducer 已经得到了 ({type: FETCH_MOVIE_REQUEST, movieId: "10" })
动作。选择器总是 returns true
.
如果我使用switchMap
,它会取消之前的请求,即使它有不同的movieId。 exhaustMap
不会 运行 下一个请求,即使它有不同的 movieId 等
现在我有了这部史诗。它适用于 cachedData
情况。如果商店已经有电影,则不会继续。但是isFetching
基于movieId还是有问题
const fetchMovieEpic = (action$, state$) =>
action$.pipe(
ofType(actionTypes.FETCH_MOVIE_REQUEST),
filter(action => {
const cachedData = selectors.selectMovie(state$.value, action.movieId);
return !verifyCachedData(cachedData, action.requiredFields);
}),
map(action => action.movieId),
switchMap(movieId =>
ajax.getJSON(`${BASE_API_URL}/movie/${movieId}?api_key=${api_key}`).pipe(
map(response => normalize(response, schemas.movieSchema)),
map(normalizedData => fetchMovieSuccess(movieId, normalizedData)),
catchError(() => of(fetchMovieError())),
takeUntil(
action$.pipe(
ofType("FETCH_MOVIE_CANCELLED"),
filter(action => action.movieId === movieId)
)
)
)
)
);
我如何使用 rxjs 运算符或任何其他技术来实现它?我不想添加像 FETCH_MOVIE_TOGGLE_LOADING
这样的额外 actionType。我已经有 REQUEST
、SUCCESS
、ERROR
和 CANCELLED
。还有很多其他的减速器和 epics。因此,使用运算符保持简单可能是一个不错的选择:)
谢谢!
根据定义 exhaustMap
假设可以工作。您可以通过重组流并简化内部流来调试它
exhaustMap(movieId =>ajax.getJSON(`${BASE_API_URL}/movie/${movieId}?api_key=${api_key}`).pipe(catchError(() => of(fetchMovieError()))
),
并查看后续操作是否会在请求完成后触发
我知道有点晚了,我实际上已经放弃使用 redux-observable。我无法用它编写我想要的代码。这让我觉得它不容易阅读。
坚持使用 redux-thunk 并在特殊情况下使用 redux-saga 可能要容易得多。至少对我来说是。
这是我在分组解决方案中使用的 epics 的最新版本: https://gist.github.com/onderonur/e55f841188263fca5ddd111d218fd505