【问题标题】:How to use the 'flatmap' operator conditionally ? (Angular 2/rxjs)如何有条件地使用“平面图”运算符? (角度 2/rxjs)
【发布时间】:2017-07-31 00:55:14
【问题描述】:

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

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

我需要检查 response1 并在需要时调用剩余的 observables,否则我需要返回 response1 并中断执行等等。

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

Conditionally choose observable in RxJS

RXJS if with observable as conditional

Handle Error in RxJs flatMap stream and continue processing

我是 rxjs 新手,如果问题看起来太蹩脚,请见谅。

任何帮助将不胜感激。

谢谢

【问题讨论】:

  • 条件是什么?是否是静态的,是否取决于response,第二个条件是否取决于response2 等?
  • 是的,条件是静态的,第二个条件取决于response2

标签: angular ecmascript-6 rxjs rxjs5 flatmap


【解决方案1】:

这就像调用多个连续的 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() 中的任何一个结果为 false,它将完成链并且不能发出其他值。

【讨论】:

  • OP 使用的concatMapflatMap 有什么区别?
  • 如果response1 是某个值,我想停止传播到observable2 并返回response1,否则运行observable2 等等
  • 您能否举例说明如何使用filter()takewhile() 停止传播
【解决方案2】:

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

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

使用订阅它

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

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

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

【讨论】:

  • 我不想合并响应,我只需要运行 observable2 如果我想。
  • 那可以单独退货吗?你为什么使用 flatMap
  • 或者如果我想运行observable2 如果response1 是某个值或者返回response1 如果它是没有嵌套的其他值,我还会使用什么
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    你可以这样做:

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

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

    【讨论】:

    • 注意:如果您希望流在此处立即完成,则“返回其他内容”可以是 Observable.empty()。你不能只返回一些类似可观察的东西,这会导致运行时错误。
    猜你喜欢
    • 1970-01-01
    • 2019-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    • 2022-08-21
    • 1970-01-01
    相关资源
    最近更新 更多