1

シナリオ:

  1. ユーザーは、単一のストリームに結合されたフィルターを使用します
  2. フィルタが変更されると、バックエンドへのイベントが発生して「安価な」データが取得されます
  3. 「安価な」データが到着すると、同じパラメーターを持つ別のリクエストが別のエンドポイントに発行され、安価なデータを充実させるために使用される「高価な」データが返されます。リクエストは 1 秒遅らせる必要があり、ユーザーがフィルターを変更しない場合にのみ発生します (それ以外の場合は 1 秒待機する必要があります)。

そして、私は3)中間変数のないオプションに苦労しています。

let filterStream = Rx.Observable
.combineLatest(
  filterX,
  filterY,
  (filterX, filterY) => {
    x: filterX,
    y: filterY
  }
 )
 .map((filters) => {
  limit: 100,
  s: filters.x.a,
  f: filters.x.b + filters.y.c,
})
.distinctUntilChanged()


let cheapDataStream = filterStream
.flatMapLatest((filterQuery) =>
Rx.Observable.fromPromise(cheapBackendApiCall(filterQuery)))

// render cheap results
cheapDataStream
.map(result => transformForDisplay(result))
.subscribe(result => { 
  //render
  // how do i invoke expensiveApiCall() with `filterQuery` data here?
  // with a delay, and only if filterQuery has not changed?

});
4

3 に答える 3

2

暗黙的な変換を利用して、fromPromiseどこでも明示的に使用することを避けることができます。次に、 concat を使用して、最初に安価なデータをすぐに返し、次に高価なデータと安価なデータを遅延して返すことができます。これをストリームに入れ子にすることで、新しいクエリが到着した場合にflatMapLatest保留中のものもキャンセルされます。expensiveCalls

var filters = Rx.Observable
.combineLatest(
  filterX,
  filterY,
  (filterX, filterY) => {
    x: filterX,
    y: filterY
  }
 )
 .map((filters) => {
  limit: 100,
  s: filters.x.a,
  f: filters.x.b + filters.y.c,
})
.distinctUntilChanged()
.flatMapLatest(filters => {
  //This kicks off immediately
  var cheapPromise = cheapBackendApiCall(filters);

  //This was added in the latest version 4.1, the function is only called once it is subscribed to, 
  //if you are using earlier you will need to wrap it in a defer instead.
  var expensivePromiseFn = () => expensiveBackendApiCall(filters);

  //For join implicitly calls `fromPromise` so you can pass the same 
  // sort of arguments.
  var cheapAndExpensive = Rx.Observable.forkJoin(
                            cheapPromise, 
                            expensivePromiseFn, 
                            (cheap, expensive) => ({cheap, expensive}));

  //First return the cheap, then wait 1500 millis before subscribing 
  //which will trigger the expensive operation and join it with the result of the cheap one
  //The parent `flatMapLatest` guarantees that this cancels if a new event comes in
  return Rx.Observable.concat(cheap, cheapAndExpensive.delaySubscription(1500));
})
.subscribe(x => /*Render results*/);
于 2016-03-22T22:53:27.153 に答える
0

do() が適切かどうかはわかりませんが、安価で高価なデータマージはあまり反応的ではありません。

Rx.Observable
.combineLatest(
  filterX,
  filterY,
  (filterX, filterY) => {
    x: filterX,
    y: filterY
  }
 )
 .map((filters) => {
  limit: 100,
  s: filters.x.a,
  f: filters.x.b + filters.y.c,
})
.distinctUntilChanged()
.flatMapLatest((filterQuery) =>
  Rx
  .Observable
  .fromPromise(cheapBackendApiCall(filterQuery))
  .map((results) => {
    filterQuery: filterQuery,
    results: results
  })
)
.do((filtersAndResults) => {
  // render filtersAndResults.results
})
.debounce(1500)
.flatMapLatest((filtersAndResults) => {
  return Rx
  .Observable
  .fromPromise(expensiveBackendApiCall(filtersAndResults.filterQuery))
  .map(results => {
    expensiveData: results,
    cheapData: filtersAndResults.results
  })
})
.subscribe((result)=> {
  // combine results.cheapData + results.expensiveData with simple .map and .find
  //  and render
})
于 2016-03-22T19:09:34.597 に答える
0

デバウンスをお探しですか?
このオペレーターは、あなたが説明したことを正確に行うようです。

于 2016-03-22T11:11:32.830 に答える