从本例中我们将用到
- fromEvent
- interval
- map
- take
- tap
- switchMapTo
业务逻辑
- 点击获取验证码按钮
- 获取验证码按钮置灰,并开始N秒倒计时
- 倒计时结束按钮恢复可点击状态
常规写法
var enabled = true
var remainTime = N
var id = null
sendBn.on('click',function(){
if(enabled){
sendSms()
enabled = false
gray(true)
remainTime = N
id = setInterval(cooldown,1000)
}
})
function cooldown(){
remainTime --
sendBn.label = remainTime + "秒后可重新获取"
if(remainTime==0){
clearInterval(id)
enabled = true
sendBn.label = "发送"
gray(false)
}
}
功能不是很复杂,但是如果你不是首先看了前面的业务逻辑,而是直接看代码,就需要稍微的理解一下才能看出里面包含了这3条逻辑。接下来我们通过Rx编程,来实现这个业务逻辑
首先我们需要一个点击事件流sendOb,每次点击按钮都会从这个sendOb中派发事件
let sendOb = fromEvent(sendBn,'click')//获取验证码点击事件
这虽然看上去和回调函数差不多,但组合起来才会显示出Rx的威力
我们还需要一个事件流用来产生倒计时
let coolDownOb = rxjs.interval(1000).pipe(map(_ => N - _), take(N))
说明一下interval(1000)会产生每秒一次的事件,0,1,2,3……
map操作,转换成了N,N-1,N-2,……(如果N=60,那么相当于60,59,58……)
take(N)操作,会在第N个事件到达后,完成事件流,interval(1000)将会停止派发事件
interval会在内部进行clearInterval操作。
下面是完成点击后发送验证码的逻辑,并且随后产生倒计时事件
let getVCodeOb = sendOb.pipe(take(1), tap(() => {
sendSms()//发送获取验证码的请求
gray(true)//显示灰色的按钮
}), switchMapTo(coolDownOb))
take(1)使得按钮的点击在订阅后只有一次有效(狂点按钮,只有第一次有效而已),如果需要再次有效,就再次订阅(也可以使用其他方法实现这种逻辑)
switchMapTo会使得事件触发后,激活coolDownOb事件流,并让订阅者开始接受这个事件流的事件。
最后我们需要订阅这个事件流,让逻辑运行起来
function enableGetVCode () {
gray(false)//恢复可点击状态
getVCodeOb.subscribe(num => sendBn.label = num + "秒后可重新获取", console.error, enableGetVCode)
}
enableGetVCode()
subscribe第三个参数是完成事件,我们将enableGetVCode传入,形成“循环”。按钮会再次被监听,开始新一轮的获取验证码
使用Rx编程后
- 不再需要定义状态变量
- 逻辑分离成完整的若干条
- 方便修改逻辑
- 可以组合出更多的逻辑,从而复用基本逻辑
网友评论