web-dev-qa-db-ja.com

以前のリクエストをキャンセルし、最新のリクエストのみを発生させる

したがって、マップが移動したときに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クエリになります。

8
MonkeyBonkey

GitHubの問題の コメント から:

それらには時間の次元があるため、オブザーバブルには複数の平坦化戦略があります。

  • mergeMap(エイリアスとしてflatMapを使用)を使用すると、受信したオブザーバブルが同時にサブスクライブされ、それらの発行された値が出力ストリームにフラット化されます。
  • concatMapを使用すると、受信したオブザーバブルがキューに入れられ、それぞれが完了するたびにサブスクライブされます。 (concatMapmergeMapであり、同時実行性は1です。)
  • switchMapを使用すると、オブザーバブルが受信されると、それがサブスクライブされ、以前に受信されたオブザーバブルへのサブスクリプションがサブスクライブ解除されます。
  • exhaustMapを使用すると、以前に受信したオブザーバブルへのサブスクリプションがなく、そのオブザーバブルがまだ完了していない場合を除いて、オブザーバブルを受信するとサブスクライブされます。この場合、受信したオブザーバブルは無視されます。

したがって、マークが彼の回答で述べたように、switchMapが後続のアクションを受信すると、不完全な要求のサブスクライブが解除されます。

ただし、デバウンスされたアクションがswitchMapに到達するまで、リクエストはキャンセルされません。デバウンス期間を待つのではなく、別の移動の直後に保留中の要求をキャンセルしたい場合は、FETCH_NEARBY_STORESアクションでtakeUntilを使用できます。

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の動作を思い出せません。takeUntilに渡されたオブザーバブルにskip(1)を追加する必要がある可能性があります。お試しください参照してください。)

そして、マークが述べたように、これはサブスクリプション解除時にリクエストをキャンセルする基本的な実装に基づいています。

12
cartant

switchMapは、新しいエミッションが送信されると、以前のオブザーバブルを破棄します。基盤となるHTTPライブラリに応じて、キャンセルがサポートされている場合(Observable対応)、これで十分です。

質問では実装の詳細が提供されていないため、fetchNearbyStoresFulfilledを調べて、Observable対応のhttpクライアントを使用しているかどうかを確認する必要があります。内部でpromiseを使用している場合、キャンセルのサポートは提供されません。

4