跟我学Rx编程——局部循环逻辑

背景

有时候,我们会遇到这种情况,事件流从一个switch到另一个,某种情况下需要从头再来一遍,比如A->B->C->A->……循环不断,这时候怎么写比较好呢?
一种写法是在subscribe里面调用“调用自身的函数”

let obA = ……
function logic(){
  obA.subscribe(...,()=>{
    logic()
  })
}

上面的伪代码里面调用了logic函数后,我们开始执行obA这个Observable的逻辑,完成后我们会立即再次调用logic,形成循环。

这种写法的不够优雅,会反复的订阅事件流,当然也不能说是错的,但是在某些场合就不适用了,比如A->B->C->D->B->C->……可能循环在B-C这段,那么上面的写法就实现不了。下面我提供一种业务场景来说明如何写

业务逻辑

  1. 执行一个远程请求获取敏感数据
  2. 如果返回特定的错误信息则进行弹窗验证身份(要求输入短信验证码)
  3. 验证不通过则再次验证,直到通过为止
  4. 验证通过,则返回有效数据

涉及操作符

  • catchError
  • switchMapTo

变量定义

let getDataOb //获取数据的Observable
let verifyOb //身份验证请求Observable

当订阅getDataOb的时候会发出请求,如果不是正常返回值,就抛出错误,此处我们省略了该Observable的创建过程
当订阅verifyOb 的时候会发出身份验证的请求,这里也省略了该Observable的创建过程,这个Observable可能是一个有多个步骤的事件流,比如需要等待用户点击发送验证码按钮等。跟我学Rx编程———获取验证码

实现过程(伪代码)

let verifyOp = catchError(err=>{
  if(err.code==VERIFY){
    return verifyOb.pipe(verfiyOp)
  }
})
getDataOb.pipe(verifyOp).subscribe(……)

伪代码已经简化了,去掉了不相干的成分。verifyOp 是一个操作符,放到外面声明,在其内部可以访问到自身的引用。
我们用到了操作符catchError,用来捕获错误,当产生特定的错误的时候,我们会返回一个Observable——verifyOb.pipe(verfiyOp),这个Obserable如果还发生错误,就会继续被捕获,形成循环,或者说递归,因为是异步请求所以严格的说不能称为递归。

思考

我们写同步代码的时候一般就用

while(condition){
}

来进行循环即可
但是当业务很复杂,需要很多异步逻辑的时候,这种写法的复杂度就会成几何级上升。此时我们使用Rx编程,可以让代码在形式上仍然保持类似递归调用的样子,方便理解整体业务,代码也更为健壮。

今天的案例可以用于其他类似的循环逻辑结构中,不局限于例子中的业务逻辑。

你可能感兴趣的:(跟我学Rx编程——局部循环逻辑)