当其中一个错误时终止Observable链

时间:2017-03-14 14:17:17

标签: android rx-java reactivex

我有一系列Rx Completables,我想一个接一个地运行。我使用concat()来执行此操作,因为我不希望它们同时启动。

view.welcome_message_edittext.verifyNotEmpty(getString(R.string.enter_your_email_address))
    .concatWith(view.welcome_message_edittext.verifyEmailAddress())
    .concatWith(sendMessageToBot())
    .subscribe({
        // The user has successfully entered data into the edittext, entered an email into the edittext, and sent message to bot. 
    }, { error -> })

上面的代码是这样说的,“断言用户已经在EditText中输入了文本。如果是这样,断言用户已经在EditText中输入了一封电子邮件。如果两者都是真的,请向机器人发送消息“。如果用户在EditText中输入文本但它不是电子邮件,我希望Completables链断开并调用onError()。

enter image description here

这就是我想要发生的事情^^^。当任何的Completables调用onError()(如verifyNotEmpty()verifyEmailAddress()时,如果用户将EditText留空或未输入电子邮件地址)那么我期待整个链终止并调用.subscribe() onError()函数。

但是,查看.concat()的文档,这就是它的实际行为:

enter image description here

concat()只会在调用onError时移至下一个Completable。链条继续。

所以我的问题是,当任何一个Completables调用onError()时,我需要使用什么来打破链?

1 个答案:

答案 0 :(得分:1)

感谢@Buckstabue在评论中帮助我调试此问题。他的评论:

  

让我猜一下。方法verifyEmailAddress()被调用是绝对正常的,我怀疑你正在一个可观察的外部做一些业务逻辑。你可以将这个逻辑放在observable中,它将被懒惰地计算它类似于Observable.just(getMyInteger())和Observable.fromCallable(() - > getMyInteger())之间的区别。在第二种情况下,getMyInteger()将在订阅后被懒惰地调用,而第一个被立即调用

返回我的代码并查看我的verifyEmailAddress()sendMessageToBot()函数:

private fun sendMessageToBot(): Completable {
    insertChatMessageIntoConversation(ChatMessage(view!!. welcome_message_edittext.text.toString()))
    return Completable.complete()
}

fun EditText.verifyEmailAddress(): Completable {
    if (!android.util.Patterns.EMAIL_ADDRESS.matcher(text.trim()).matches()) {
        return Completable.error(RuntimeException("Enter a valid email"))
    } else {
        return Completable.complete()
    }
}

函数的逻辑不是块中的 。当我编写代码时,我认为这并不重要,因为我认为Rx的行为是它执行每个Completable并等待它们完成或完全错误,然后再转到下一个Completeable。因此,完全跳过sendMessageToBot()verifyEmailAddress()函数。不是这样的。

这有效:

fun EditText.verifyEmailAddress(): Completable {
    return Completable.fromCallable({
        if (!android.util.Patterns.EMAIL_ADDRESS.matcher(text.trim()).matches()) {
            val errorMessage = context.getString(R.string.enter_email_address)
            error = errorMessage
            throw RuntimeException(errorMessage)
        }
    })
}

private fun sendMessageToBot(): Completable {
    return Completable.fromCallable {
        insertChatMessageIntoConversation(sage(view!!. welcome_message_edittext.text.toString()))
    }
}