Мы можем использовать одновременный на MergeMap, но я думаю, что это вызвало наращивание. Могу ли я установить одновременный выпуск для Выхлопной карты?

interval(500).pipe(
  mergeMap(timer(3000), 3)
)
4
molysama 17 Авг 2019 в 05:47

2 ответа

Лучший ответ

Вы можете создать такого оператора самостоятельно. Вот возможная реализация:

const { interval, timer, of, empty } = rxjs
const { mergeMap, map, tap, filter } = rxjs.operators

const exhaustMapWithConcurrency = 
  (selector, concurrency = 1) => 
    source => {
  let active = 0;
  return source.pipe(
    filter(_ => active < concurrency),
    tap(_ => active++),
    mergeMap(selector),
    tap(_ => active--)
  )
}

interval(500).pipe(
  exhaustMapWithConcurrency(x => 
    timer(3000).pipe(
      map(_ => x)
    ), 3)
)
.subscribe(console.log)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.2/rxjs.umd.min.js"></script>
2
ZahiC 17 Авг 2019 в 11:57

Так что я нашел довольно хакерский способ достижения того, что, как мне кажется, вы ищете. В этом примере я использовал переменную toggle, но, конечно, вы можете использовать любой логический генератор:

toggle = true;
concurrent = 5;

interval(500).pipe(
  filter(() => this.toggle), // are we still accepting values?
  mergeMap((val, index) => {
    // when we hit our concurrency limit, stop accepting values
    if (index % this.concurrent === 0 && index !== 0) {
      this.toggle = false;
    }
    // I added a proportional delay to show that values are ignored
    return of(val).pipe(delay(500 * val));
  }),
  mergeMap((val, index) => {
    // once the preset number of values have been passed down the pipe,
    // meaning our concurrent mergeMaps are complete,
    // start accepting values again
    if (index % this.concurrent === 0 && index !== 0) {
      this.toggle = true;
    }
    return of(val);
  }),
  tap(console.log)
).subscribe();

Это, конечно, просто демонстрация концепции. Это похоже на то, что вы ищете?

1
Will Alexander 17 Авг 2019 в 10:01