Javascript 如何一次处理RxJS流n个项目,一旦一个项目完成,自动填充回n?

Javascript 如何一次处理RxJS流n个项目,一旦一个项目完成,自动填充回n?,javascript,rxjs,backpressure,Javascript,Rxjs,Backpressure,我有一个事件流,我想调用一个函数,为每个事件返回一个承诺,问题是这个函数非常昂贵,所以我想一次最多处理n个事件 这个鹅卵石图可能是错误的,但这正是我想要的: ---x--x--xxxxxxx-------------x-------------> //Events ---p--p--pppp------p-p-p-----p-------------> //In Progress -------d--d--------d-d-dd------dddd--------> /

我有一个事件流,我想调用一个函数,为每个事件返回一个承诺,问题是这个函数非常昂贵,所以我想一次最多处理n个事件

这个鹅卵石图可能是错误的,但这正是我想要的:

---x--x--xxxxxxx-------------x------------->  //Events
---p--p--pppp------p-p-p-----p------------->  //In Progress
-------d--d--------d-d-dd------dddd-------->  //Promise Done

---1--21-2-34-----------3----4-3210--------   //QUEUE SIZE CHANGES
这是我目前掌握的代码:

var n = 4;
var inProgressCount = 0;

var events$ = Rx.Observable.fromEvent(produceEvent, 'click')
  .map((ev) => new Date().getTime());

var inProgress$ = events$.controlled();

var done$ = inProgress$      
  .tap(() => inProgressCount++)
  .flatMap((timestamp) => Rx.Observable.fromPromise(expensiveComputation(getRandomInt(1, 5) * 1000, timestamp)));

done$.subscribeOnNext((timestamp) => {
  inProgressCount--;
  inProgress$.request(Math.max(1, n - inProgressCount));
});

inProgress$.request(n);
此代码有两个问题:

  • 它使用的是
    inProgressCount
    var,该变量用side更新 效果函数
  • 当我从受控流请求超过1项时,只调用一次done$订阅。这使得
    inProgressCount
    var更新不正确,最终将队列限制为一次一个
  • 您可以在这里看到它的工作原理:

    问题:

  • 有更好的方法吗
  • 如何去掉
    inProgressCount
    变量
  • 为什么在请求多个项目时只调用一次done$订阅
  • 更新:

    问题#3的答案:switchMap与flatMapLatest相同,所以我只得到最后一个。将代码更新为flatMap而不是switchMap。

    实际上根本不需要使用背压。有一个名为
    flatMapWithMaxConcurrent
    的操作符可以为您执行此操作。它本质上是调用
    .map().merge(concurrency)
    的别名,并且一次只允许最大数量的流处于运行状态

    我在这里更新了您的jsbin:

    但我在下面注释了重要的一点:

    const concurrency = 4;
    
    var done$ = events$
      //Only allows a maximum number of items to be subscribed to at a time
      .flatMapWithMaxConcurrent(concurrency, 
        ({timestamp}) =>   
          //This overload of `fromPromise` defers the execution of the lambda
          //until subscription                    
          Rx.Observable.fromPromise(() => { 
            //Notify the ui that this task is in progress                                 
            updatePanelAppend(inProgress, timestamp);
            removeFromPanel(pending, timestamp);
            //return the task
            return expensiveComputation(getRandomInt(1, 5) * 1000, timestamp)
         }));
    

    在RxJs 5中,必须将.flatMapWithMaxConcurrent替换为.mergeMap(映射器,(resultSelectorFunction | null),并发)