取消之前的请求,只使用 redux observable 触发最新的请求 [英] Cancel previous requests and only fire the latest request with redux observable

查看:57
本文介绍了取消之前的请求,只使用 redux observable 触发最新的请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有一个用例,我在移动地图时更新 api 请求 - 但它可能会生成几个带有小地图移动的快速请求 - 我想取消除最后一个之外的所有飞行请求.我可以使用 debounce 仅在延迟后发送请求.但是,如果它们碰巧仍在处理中,我仍然想取消任何旧请求.

So I have use case where I update the api request when the map is moved - but it could generate several rapid fire requests with small map movements - and I want to cancel all the inflight requests except for the last one. I can use debounce to only send requests after a delay. However I still want to cancel any old requests if they happen to still be in process.

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 查询.

I see that you can use takeUntil but you need to explicitly fire a cancel action. I see in the docs that switchMap will take the latest and cancel all the others - do I have to implement a cancel interface in my api call? In this case it would be a firebase query to firestore.

推荐答案

来自 我在 GitHub 问题中发表的评论:

因为它们有时间维度,所以有多种可观察的扁平化策略:

Because they have a time dimension, there are multiple flattening strategies for observables:

  • 使用 mergeMap(以 flatMap 作为别名),接收到的 observable 被并发订阅,并且它们发出的值被扁平化到输出流中.
  • 使用 concatMap,接收到的 observable 被排队并在每个完成时一个接一个订阅.(concatMapmergeMap,并发为 1.)
  • 使用 switchMap,当收到一个 observable 时,它​​会被订阅,而对之前收到的 observable 的任何订阅都将取消订阅.
  • 使用 exhaustMap,当收到 observable 时,它​​会被订阅,除非订阅了之前收到的 observable 并且该 observable 尚未完成 - 在这种情况下,接收到的 observable 将被忽略.立>
  • 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 收到后续动作时,它将取消订阅任何未完成的请求.

So, like Mark said in his answer, when switchMap receives a subsequent action, it will unsubscribe from any incomplete request.

但是,在去抖动的动作到达switchMap 之前,请求不会被取消.如果您想在另一次移动时立即取消任何挂起的请求 - 而不是等待去抖动持续时间 - 您可以使用 takeUntilFETCH_NEARBY_STORES 操作:

However, the request won't be cancelled until the debounced action makes it to the switchMap. If you want to cancel any pending requests immediately upon another move - rather than wait for the debounce duration - you can use takeUntil with the FETCH_NEARBY_STORES action:

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))
    );

这应该会在另一次移动时立即取消订阅请求.(在我的脑海里,我想不起来 redux-observableaction$ 的行为.你可能需要附加一个 skip(1) 到传递给 takeUntil 的 observable.试试看.)

That should effect the immediate unsubscription from a request upon another move. (Off the top of my head, I cannot recall the behaviour of action$ in redux-observable. It's possible that you might need to append a skip(1) to the observable passed to takeUntil. Try it and see.)

而且,正如 Mark 所提到的,这是基于底层实现在取消订阅时取消请求.

And, as Mark mentioned, this is predicated on the underlying implementation cancelling the request upon unsubscription.

这篇关于取消之前的请求,只使用 redux observable 触发最新的请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆