RxJS中如何在timer倒计时结束后调用指定函数
RxJS timer 计时结束触发函数实现方案
你当前代码中使用的tap会在timer每一次发射值时都执行,并非计时结束才触发。同时takeWhile(x => x >= 0)默认会在x第一次小于0时直接终止流,不会将终止对应的信号值传递给下游的tap,因此无法通过普通tap捕获到结束时机。
下面是三种可直接落地的实现方式:
方案1:使用finalize操作符(最推荐)
finalize会在Observable正常结束、报错、取消订阅时统一触发,完全匹配计时结束的执行场景:
import { finalize } from 'rxjs/operators'; // 注意milliseconds要提前定义为你的总计时毫秒数 this.timer$ = timer(1000, 1000).pipe( scan(acc => acc - 1000, milliseconds), takeWhile(x => x >= 0), // 每次倒计时跳动要执行的逻辑可以写在这里 tap(currentRemaining => { console.log('当前剩余毫秒:', currentRemaining) }), // 计时结束后要调用的函数写在finalize里 finalize(() => { console.log('计时结束') yourTargetFunction() // 替换为你要调用的目标函数 }) ) // 必须订阅流才会运行,漏写订阅会导致整个timer不生效 this.timer$.subscribe()
方案2:在subscribe的complete回调中执行
如果不需要在pipe链里处理结束逻辑,也可以直接在订阅时传入complete回调:
this.timer$ = timer(1000, 1000).pipe( scan(acc => acc - 1000, milliseconds), takeWhile(x => x >= 0) ) this.timer$.subscribe({ next: (currentRemaining) => console.log('当前剩余毫秒', currentRemaining), complete: () => { console.log('计时结束') yourTargetFunction() // 替换为你要调用的目标函数 } })
方案3:开启takeWhile的emitLast参数配合tap判断
如果需要拿到结束时的最后一个值再处理,可以开启takeWhile的第二个参数emitLast,将最后一个不符合条件的值也发射出来,再用tap判断执行:
this.timer$ = timer(1000, 1000).pipe( scan(acc => acc - 1000, milliseconds), // 第二个参数设为true,会发射导致流终止的那个值 takeWhile(x => x >= 0, true), tap(current => { if (current < 0) { console.log('计时结束') yourTargetFunction() // 替换为你要调用的目标函数 } else { console.log('倒计时中:', current) } }) ).subscribe()
内容的提问来源于stack exchange,提问作者cakePHP
相关产品推荐
相关产品推荐

