包含确认

时间:2017-09-28 12:41:04

标签: rxjs observable

我正在研究记录来自队列的数据。很容易将队列处理成Observable,这样我的代码中就可以有多个端点接收队列中的信息。

此外,我可以确定信息按顺序到达。由于Observables确保这一点,所以这一点也能很好地工作。 但是,一个棘手的问题是我不希望Observer在完成处理前一个事情之前被通知下一件事。但Observer完成的处理是异步的。

作为一个更具体的例子,可能很容易遵循。想象一下,我的队列包含URL。我在我的代码中将它们暴露为Observable。我订阅了一个Observer,它的工作是获取URL并将内容写入磁盘(这是一个人为的例子,因此不要对这些细节产生问题)。重要的是获取和保存是异步的。我的问题是,我不希望观察者从Observable获得“下一个”URL,直到他们完成上一次处理。

但Observer接口上对next的调用返回void。因此,Observer无法与实际完成异步任务的人进行通信。

有什么建议吗?我怀疑可能有某种类型的运算符可以编码,它基本上会保留未来的值(在内存中将它们排队?),直到它以某种方式知道Observer已准备就绪。但我希望在一些既定的模式之后已存在类似的事情。

3 个答案:

答案 0 :(得分:1)

之前碰到的类似用例

window.document.onkeydown=(e)=>{
  return false
}
let count=0;
let asyncTask=(name,time)=>{
  time=time || 2000
  return Rx.Observable.create(function(obs) {
      setTimeout(function() {
       count++
        obs.next('task:'+name+count);
           console.log('Task:',count ,'   ', time, 'task complete') 
        obs.complete();
      }, time);
    });
}

let subject=new Rx.Subject()
let queueExec$=new Rx.Subject()


Rx.Observable.fromEvent(btnA, 'click').subscribe(()=>{
 queueExec$.next(asyncTask('A',4000)) 
})

Rx.Observable.fromEvent(btnB, 'click').subscribe(()=>{
 queueExec$.next(asyncTask('B',4000)) 
})

Rx.Observable.fromEvent(btnC, 'click').subscribe(()=>{
 queueExec$.next(asyncTask('C',4000)) 
})

  queueExec$.concatMap(value=>value)
    .subscribe(function(data) {
      console.log('onNext', data);
    }, 
    function(error) {
      console.log('onError', error);
    },function(){
 console.log('completed') 
});

答案 1 :(得分:1)

你所描述的听起来像“背压”。您可以在RxJS 4文档https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/backpressure.md中阅读相关内容。然而,这提到了RxJS 5中不存在的运算符。例如,看一下应该引用你需要的“受控Observables”。

我认为您可以使用concatMap和主题实例

实现相同目标
const asyncOperationEnd = new Subject();

source.concatMap(val => asyncOperationEnd
    .mapTo(void 0)
    .startWith(val)
    .take(2) // that's `val` and the `void 0` that ends this inner Observable
  )
  .filter(Boolean) // Always ignore `void 0`
  .subscribe(val => {
    // do some async operation...
    // call `asyncOperationEnd.next()` and let `concatMap` process another value
  });

你的描述实际上看起来像是“观察者”你提到像Subject一样的作品,所以制作一个你可以在任何Observable链中使用的自定义Subject类会更有意义。

答案 2 :(得分:0)

这不仅仅是concatMap吗?

// Requests are coming in a stream, with small intervals or without any.
const requests=Rx.Observable.of(2,1,16,8,16)
    .concatMap(v=>Rx.Observable.timer(1000).mapTo(v));

// Fetch, it takes some time.
function fetch(query){
  return Rx.Observable.timer(100*query)
      .mapTo('!'+query).startWith('?'+query);
}

requests.concatMap(q=>fetch(q));

https://rxviz.com/v/Mog1rmGJ

如果要同时允许多次提取,请将mergeMap与并发参数一起使用。