如何有条件地使用'flatmap'运算符? (Angular 2 / rxjs)

时间:2017-03-09 21:13:33

标签: angular ecmascript-6 rxjs rxjs5 flatmap

我想要实现的是有条件地运行一系列可观察量。

return observable.map(response => response)
       .flatmap(response1 => observable1(response1))
       .flatmap(response2 => observable2(response2))
       .flatmap(response3 => observable3(response3))

我需要检查response1并在需要时调用剩余的observable,否则我需要返回response1并中断执行,依此类推。

我已经完成了以下SO问题,但他们似乎没有回答我的问题

  

Conditionally choose observable in RxJS

     

RXJS if with observable as conditional

     

Handle Error in RxJs flatMap stream and continue processing

我是rxjs的新手,如果这个问题看起来太蹩脚,请原谅我。

任何帮助将不胜感激。

由于

4 个答案:

答案 0 :(得分:5)

这就像调用多个连续的HTTP请求,其中结果相互依赖。这是你想要使用concatMap()的地方,因为它会等到从回调函数返回的Observable完成。

很难说明你想从描述中做些什么,但如果你需要停止传播结果(并避免调用不必要的HTTP请求),请看一下takeWhile()运算符或简单的filter()运算符

使用filter()

return observable
    .concatMap(response => response)
    .filter(response1 => response1.whatever === true)
    .concatMap(response1 => observable1(response1))
    .filter(response2 => response2.whatever === true)
    .concatMap(response2 => observable2(response2))
    .filter(response3 => response3.whatever === true)

如果filter测试失败,这将不会进一步传播该项目。但是,源observable仍然可以发出将通过链的值。换句话说,filter运算符无法完成链。

使用takeWhile()

return observable
    .concatMap(response => response)
    .takeWhile(response1 => response1.whatever === true)
    .concatMap(response1 => observable1(response1))
    .takeWhile(response2 => response2.whatever === true)
    .concatMap(response2 => observable2(response2))
    .takeWhile(response3 => response3.whatever === true)

如果任何takeWhile()导致错误,它将完成链并且不会发出其他值。

答案 1 :(得分:2)

您可以执行以下操作:

observable.map(res => res.json())
  .flatMap(json => {
      if (json.something === 'something') {
          return this.http.get('/anotherCall')
              .map(res => 'second response: ' + res);
      } else {
          return Observable.from(['just return something else']);
      }
  });

只有两个电话,但你明白了。

答案 2 :(得分:1)

我没有找到绕过运营商的简单方法,如果您决定跳过最后一个运营商,您仍然需要通过所有运营商传递最后一个有效响应:

 return observable
   .flatmap(r => {
        return r.value > 1 ? observable1(r) : Observable.of(r);
   })
   .flatmap(r => {
        return r.value > 2 ? observable2(r) : Observable.of(r);
   })
   .flatmap(r => {
        return r.value > 3 ? observable3(r) : Observable.of(r);
   })

答案 3 :(得分:0)

或者,您可以将所有可观察对象组合成一个单独的可观察对象并订阅,如下所示,

return response
         .concatMapTo(response1,(response2, response3) => 
             `${response2} ${response3}`
          );

使用

订阅
data = response.subscribe(val => console.log(val)); // contains all three responses value

您仍然可以使用response2response3命名实例分别访问每个。

使用不同的observable订阅单个对象: 如果您希望将来自不同观察点的数据和属性组合起来,可以查看 answer