取消之前的请求,仅使用redux observable

时间:2018-05-03 17:04:25

标签: rxjs redux-observable

所以我有一个用例,我在移动地图时更新api请求 - 但它可以生成几个带有小地图移动的快速火灾请求 - 我想取消除最后一个之外的所有飞行请求。我可以使用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查询。

2 个答案:

答案 0 :(得分:7)

来自GitHub问题中的comment I made

  

因为它们有时间维度,所以对于可观察对象有多种展平策略:

     
      
  • 使用mergeMap(其中flatMap作为别名),收到的observables会同时订阅,并且它们的发布值会被平展到输出流中。
  •   
  • 使用concatMap,收到的可观察对象排队,并在每个完成时一个接一个地订阅。 (concatMapmergeMap,并发为一。)
  •   
  • 使用switchMap,当收到一个观察者时,它已订阅,并且对以前收到的观察者的任何订阅都已取消订阅。
  •   
  • 使用exhaustMap,当收到一个observable时,它会订阅,除非订阅了之前收到的observable并且该observable尚未完成 - 在这种情况下,接收的observable将被忽略。< / LI>   

所以,就像马克在答案中所说,当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)附加到传递给{的观察者身上{1}}。试一试,看看。)

而且,正如马克所说,这取决于取消订阅时取消请求的基础实施。

答案 1 :(得分:4)

当通过它发送新的发射时,

switchMap将放弃其先前的可观测量。根据您的基础HTTP库以及它是否支持取消(Observable aware),这应该足够了。

由于您的问题中未提供任何实施细节,因此您必须查看fetchNearbyStoresFulfilled以查看它是否使用了Observable感知的http客户端。如果它在内部使用promises,则不提供取消支持。