取消之前的请求,只用 redux observable 触发最新的请求
Cancel previous requests and only fire the latest request with redux observable
所以我有一个用例,当地图移动时我更新 api 请求 - 但它可能会生成多个 rapid 小地图移动的开火请求 - 我想取消除最后一个请求外的所有机上请求。我可以使用 debounce 仅在延迟后发送请求。但是我仍然想取消任何旧的请求,如果它们恰好仍在处理中的话。
const fetchNearbyStoresEpic = action$ =>
action$.ofType(FETCH_NEARBY_STORES)
.debounceTime(500)
.switchMap(action =>
db.collection('stores')
.where('location', '<=', action.payload.max).
.where('location', '>=', action.payload.min)
.map(response => fetchNearbyStoresFulfilled(response))
.takeUntil(action$.ofType(FETCH_STORES_CANCELLED))
);
我看到您可以使用 takeUntil
,但您需要明确触发取消操作。我在文档中看到 switchMap 将采用最新的并取消所有其他 - 我是否必须在我的 api 调用中实现取消接口?在这种情况下,它将是对 firestore 的 firebase 查询。
switchMap
将在通过它发送新发射时放弃其先前的可观察性。根据您的底层 HTTP 库,如果它支持取消(可观察到),这就足够了。
因为您的问题中没有提供实施细节,您将不得不查看 fetchNearbyStoresFulfilled
以查看它是否使用 Observable 感知的 http 客户端。如果它在内部使用承诺,则不提供取消支持。
来自 GitHub 问题中的 comment I made:
Because they have a time dimension, there are multiple flattening strategies for observables:
- With
mergeMap
(which has flatMap
as an alias), received observables are subscribed to concurrently and their emitted values are flattened into the output stream.
- With
concatMap
, received observables are queued and are subscribed to one after the other, as each completes. (concatMap
is mergeMap
with a concurrency of one.)
- With
switchMap
, when an observable is received it's subscribed to and any subscription to a previously received observable is unsubscribed.
- With
exhaustMap
, when an observable is received it's subscribed to unless there is a subscription to a previously received observable and that observable has not yet completed - in which case the received observable is ignored.
因此,正如 Mark 在他的回答中所说,当 switchMap
收到后续操作时,它将取消订阅任何未完成的请求。
但是,在去抖动作到达 switchMap
之前,请求不会被取消。如果您想在另一次移动后立即取消任何未决请求 - 而不是等待去抖持续时间 - 您可以使用 takeUntil
和 FETCH_NEARBY_STORES
操作:
const fetchNearbyStoresEpic = action$ =>
action$.ofType(FETCH_NEARBY_STORES)
.debounceTime(500)
.switchMap(action =>
db.collection('stores')
.where('location', '<=', action.payload.max).
.where('location', '>=', action.payload.min)
.map(response => fetchNearbyStoresFulfilled(response))
.takeUntil(action$.ofType(FETCH_NEARBY_STORES))
);
这应该会影响在另一个移动时立即取消订阅请求。 (我想不起来 action$
在 redux-observable
中的行为。您可能需要将 skip(1)
附加到传递给 takeUntil
的可观察对象.试试看。)
并且,正如 Mark 所提到的,这是基于取消订阅时取消请求的基础实现。
所以我有一个用例,当地图移动时我更新 api 请求 - 但它可能会生成多个 rapid 小地图移动的开火请求 - 我想取消除最后一个请求外的所有机上请求。我可以使用 debounce 仅在延迟后发送请求。但是我仍然想取消任何旧的请求,如果它们恰好仍在处理中的话。
const fetchNearbyStoresEpic = action$ =>
action$.ofType(FETCH_NEARBY_STORES)
.debounceTime(500)
.switchMap(action =>
db.collection('stores')
.where('location', '<=', action.payload.max).
.where('location', '>=', action.payload.min)
.map(response => fetchNearbyStoresFulfilled(response))
.takeUntil(action$.ofType(FETCH_STORES_CANCELLED))
);
我看到您可以使用 takeUntil
,但您需要明确触发取消操作。我在文档中看到 switchMap 将采用最新的并取消所有其他 - 我是否必须在我的 api 调用中实现取消接口?在这种情况下,它将是对 firestore 的 firebase 查询。
switchMap
将在通过它发送新发射时放弃其先前的可观察性。根据您的底层 HTTP 库,如果它支持取消(可观察到),这就足够了。
因为您的问题中没有提供实施细节,您将不得不查看 fetchNearbyStoresFulfilled
以查看它是否使用 Observable 感知的 http 客户端。如果它在内部使用承诺,则不提供取消支持。
来自 GitHub 问题中的 comment I made:
Because they have a time dimension, there are multiple flattening strategies for observables:
- With
mergeMap
(which hasflatMap
as an alias), received observables are subscribed to concurrently and their emitted values are flattened into the output stream.- With
concatMap
, received observables are queued and are subscribed to one after the other, as each completes. (concatMap
ismergeMap
with a concurrency of one.)- With
switchMap
, when an observable is received it's subscribed to and any subscription to a previously received observable is unsubscribed.- With
exhaustMap
, when an observable is received it's subscribed to unless there is a subscription to a previously received observable and that observable has not yet completed - in which case the received observable is ignored.
因此,正如 Mark 在他的回答中所说,当 switchMap
收到后续操作时,它将取消订阅任何未完成的请求。
但是,在去抖动作到达 switchMap
之前,请求不会被取消。如果您想在另一次移动后立即取消任何未决请求 - 而不是等待去抖持续时间 - 您可以使用 takeUntil
和 FETCH_NEARBY_STORES
操作:
const fetchNearbyStoresEpic = action$ =>
action$.ofType(FETCH_NEARBY_STORES)
.debounceTime(500)
.switchMap(action =>
db.collection('stores')
.where('location', '<=', action.payload.max).
.where('location', '>=', action.payload.min)
.map(response => fetchNearbyStoresFulfilled(response))
.takeUntil(action$.ofType(FETCH_NEARBY_STORES))
);
这应该会影响在另一个移动时立即取消订阅请求。 (我想不起来 action$
在 redux-observable
中的行为。您可能需要将 skip(1)
附加到传递给 takeUntil
的可观察对象.试试看。)
并且,正如 Mark 所提到的,这是基于取消订阅时取消请求的基础实现。