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

4
我想要实现的是有条件地运行一系列可观察对象。
return observable.map(response => response)
       .flatmap(response1 => observable1(response1))
       .flatmap(response2 => observable2(response2))
       .flatmap(response3 => observable3(response3))

我需要检查response1并在需要时调用其余的observables,否则我需要返回response1并中断执行等等。
我已经查看了以下SO问题,但它们似乎没有回答我的问题: 在RxJS中有条件地选择observable RXJS中使用observable作为条件的if语句 处理RxJs flatMap流中的错误并继续处理 我是rxjs的新手,所以如果问题看起来太简单,请原谅。
任何帮助将不胜感激。
谢谢。

条件基于什么?它是静态的吗?它是否依赖于“response”?第二个条件是否依赖于“response2”等等? - Bergi
是的,这个条件是静态的,第二个条件取决于 response2 - Joel Raju
4个回答

6
这就像调用多个连续的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)

如果项目未通过过滤器测试,则它将不会进一步传播。但是源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()的任何结果为false,它将完成链式操作,并且不会发出其他值。

“concatMap”和OP使用的“flatMap”有何区别? - Bergi
如果response1是特定值,我想停止向 observable2 的传播并返回response1,否则运行observable2等等。 - Joel Raju
你能展示一下如何使用 filter()takewhile() 来停止事件传播的例子吗? - Joel Raju

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']);
      }
  });

只需两个调用,你就能明白了。


请注意:如果您希望流立即完成,则“return something else”可以是Observable.empty()。您不能只是不返回任何类似于可观察的东西,否则会导致运行时错误。 - Pac0

1
我发现没有简单的方法来绕过操作符,如果你决定跳过最后n个操作符,你仍然需要通过所有操作符传递最后一个有效的响应。
 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);
   })

0

或者,您可以将所有可观察对象合并为一个单一的可观察对象,并按如下订阅:

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

使用它进行订阅

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

尽管如此,您仍然可以使用名为response2response3的实例分别访问每个实例。

使用不同的可观察对象订阅单个对象: 如果您想要将来自不同可观察对象的数据和属性组合在一起,可以查看这个answer


我不想合并这些响应,只有在需要时才运行observable2 - Joel Raju
你能单独返回吗?为什么要使用flatMap - Aravind
如果我想在response1是某个特定值时运行observable2,或者在response1是其他值时返回response1而不嵌套,我还能用什么? - Joel Raju

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接