来自RxJS

时间:2016-02-03 20:27:59

标签: javascript reactive-programming rxjs

我是RxJS的新手,想知道是否有人可以帮助我。

我想从请求流(有效负载数据)创建一个同步的响应流(最好带有相应的请求)。

我基本上希望逐个发送请求,每个请求等待最后一个请求。

我尝试了这个,但它会立即发送所有内容(jsbin):



var requestStream, responseStream;
requestStream = Rx.Observable.from(['a','b','c','d','e']);

responseStream = requestStream.flatMap(
  sendRequest,
  (val, response)=>{ return {val, response}; }
);

responseStream.subscribe(
  item=>{
    console.log(item);
  },
  err => {
    console.err(err);
  },
  ()=>{
    console.log('Done');
  }
);

function sendRequest(val) {
  return new Promise((resolve,reject)=>{
    setTimeout(()=>{resolve('result for '+val);},1000);
  });
};




以下工作在某种程度上,但不会对请求数据使用流(jsbin)。



var data, responseStream;
data = ['a','b','c','d','e'];
responseStream = Rx.Observable.create(observer=>{
  var sendNext = function(){
    var val = data.shift();
    if (!val) {
      observer.onCompleted();
      return;
    }
    sendRequest(val).then(response=>{
      observer.onNext({val, response});
      sendNext();
    });
  };
  sendNext();
});

responseStream.subscribe(
  item=>{
    console.log(item);
  },
  err => {
    console.err(err);
  },
  ()=>{
    console.log('Done');
  }
);

function sendRequest(val) {
  return new Promise((resolve,reject)=>{
    setTimeout(()=>{resolve('response for '+val);},Math.random() * 2500 + 500);
  });
};




谢谢!

修改

只是澄清一下,这就是我想要实现的目标:

"发送A,当您收到A的回复时,发送B,当您收到B的回复时,发送C等..."

使用concatMap和defer,正如user3743222所建议的那样,似乎是这样做的(jsbin):

responseStream = requestStream.concatMap(
  (val)=>{
    return Rx.Observable.defer(()=>{
      return sendRequest(val);
    });
  },
  (val, response)=>{ return {val, response}; }
);

1 个答案:

答案 0 :(得分:3)

尝试在第一个代码示例中用flatMap替换concatMap,并告诉我结果行为是否与您要查找的内容相符。

responseStream = requestStream.concatMap(//I replaced `flatMap`
  sendRequest,
  (val, response)=>{ return {val, response}; }
);

基本上concatMap具有与flatMap类似的签名,行为的差异在于它会等待当前的observable在继续下一个之前被展平。所以这里:

  • requestStream值将被推送到concatMap运营商。
  • concatMap运算符将生成sendRequest observable,并且该observable中的任何值(似乎是元组(val, response))都将通过选择器函数和对象结果传递其中将通过下游
  • sendRequest完成时,将处理另一个requestStream值。
  • 简而言之,您的请求将逐一处理

或者,您可能希望使用defer来推迟执行sendRequest

responseStream = requestStream.concatMap(//I replaced `flatMap`
  function(x){return Rx.Observable.defer(function(){return sendRequest(x);})},
  (val, response)=>{ return {val, response}; }
);