如何在 RxJava2 中链接两个 Completable

新手上路,请多包涵

我有两个可完成的。我想做以下场景:如果第一个 Completable 到达 onComplete ,则继续第二个 Completable。最终结果将是第二个 Completable 的 onComplete。

当我有 Single getUserIdAlreadySavedInDevice() 和 Completable login() 时,我就是这样做的:

 @Override
public Completable loginUserThatIsAlreadySavedInDevice(String password) {
    return getUserIdAlreadySavedInDevice()
            .flatMapCompletable(s -> login(password, s))

}

原文由 Mladen Rakonjac 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 481
2 个回答

您正在寻找 andThen 操作员。

返回一个 Completable,它首先运行此 Completable,然后运行另一个 Completable。

 firstCompletable
    .andThen(secondCompletable)

通常,此运算符是 flatMap 上的 Completable 的“替代品”:

 Completable       andThen(CompletableSource next)
<T> Maybe<T>      andThen(MaybeSource<T> next)
<T> Observable<T> andThen(ObservableSource<T> next)
<T> Flowable<T>   andThen(Publisher<T> next)
<T> Single<T>     andThen(SingleSource<T> next)

原文由 Maksim Ostrovidov 发布,翻译遵循 CC BY-SA 3.0 许可协议

TL;DR:其他答案遗漏了一个微妙之处。 Use doThingA().andThen(doThingB()) if you want the equivalent of concat , use doThingA().andThen(Completable.defer(() -> doThingB()) if you want the equivalent of flatMap .


编辑:更完整的参考

  • flatMap()merge() 的映射版本
  • concatMap()concat() 的映射版本
  • For a Completable you need defer() to make function calls lazy like in the mapping functions for Single or Observable (or preferably make it so在你点击订阅之前什么都不会发生——这是一个很好的约定,并在官方 Rx 库和我遇到的任何 Rx 扩展中使用,对于高级用户,这仅指冷可完成的,但大多数人可以忽略它) .
  • concat(a, b)a.andThen(b) 之间的唯一区别是语法

一些例子:

  • foo(a).andThen(bar(b)) 将:

    1. 呼叫 foo(a)
    2. 立即调用 bar(b) 即使步骤返回的可 1 返回错误
    3. 订阅任何步骤 1 返回
    4. 仅当最后一步成功完成时,才会 订阅 bar(b) 的结果
  • foo(a).andThen(Completable.defer(() -> bar(b)) 将:

    1. 呼叫 foo(a)
    2. 订阅步骤的结果 1
    3. 仅当 foo(a) 返回的可完成项成功时才调用 bar(b)

我将省略 merge() 的处理,因为它变得有点复杂,但长话短说,如果你想要“并行性”,那就是调用它。


上面的答案在某种程度上是正确的,但我发现它们具有误导性,因为它们忽略了关于急切评估的微妙之处。

doThingA().andThen(doThingB()) will call doThingB() immediately but only subscribe to the observable returned by doThingB() when the observable returned by doThingA() completes.

doThingA().andThen(Completable.defer(() -> doThingB()) 将调用 doThingB() 只有在事情 A 完成后。

仅当 doThingB() 在订阅事件之前有副作用时,这才重要。例如 Single.just(sideEffect(1)).toCompletable()

在订阅事件(真正的冷可观察对象)之前没有副作用的实现可能是 Single.just(1).doOnSuccess(i -> sideEffect(i)).toCompletable()

在这种情况下,A 是一些验证逻辑和 doThingB() 立即启动异步数据库更新,完成 VertX ObservableFuture。这是不好的。可以说 doThingB() 应该写成只在订阅时更新数据库,我将在未来尝试以这种方式设计。

原文由 Sparky 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题