实现带初始延迟的持久化Spinner需使用哪些RxJS操作符?
实现Spinner加载逻辑的RxJS操作符组合
嘿,这个Spinner的加载逻辑我之前做项目时刚好遇到过!RxJS的几个操作符组合起来就能完美搞定,咱们先把需求再理清楚,然后对应操作符来拆解:
你的需求核心是根据isLoading的状态变化,结合两个时间阈值(initialDelay和minSpinTime)来控制Spinner的显示/隐藏,三个场景本质是要处理「延迟显示」和「强制最小显示时长」两个关键点。
核心操作符及作用
我会用以下几个操作符组合,每个都对应一个关键逻辑:
distinctUntilChanged:首先得过滤掉isLoading连续重复的状态(比如多次连续设为true/false),避免流被不必要的重复触发,这是处理状态流的常规操作。switchMap:这是实现逻辑的核心!它的作用是每当新的isLoading状态到来时,取消之前正在执行的内部流。比如如果在initialDelay内就把isLoading设为false,switchMap会直接终止之前等待initialDelay的流,Spinner就不会显示,完美对应第一个场景。timer:用来创建延迟触发的流,分别对应initialDelay(等待是否要显示Spinner)和minSpinTime(保证Spinner至少显示的时长)。race:用来判断两个事件哪个先发生——当Spinner已经显示后,我们需要看是「isLoading变为false」先发生,还是「minSpinTime时长到」先发生,取先发生的那个来决定后续逻辑。startWith:用来设置流的初始状态,比如在等待initialDelay期间,Spinner的显示状态是false。
具体实现代码示例
假设你已经有一个isLoading$的Observable(比如从组件的输入属性或者状态管理中获取),可以这样组合操作符:
import { of, timer, race } from 'rxjs'; import { switchMap, distinctUntilChanged, startWith, filter } from 'rxjs/operators'; // 定义你的时间阈值,单位毫秒 const initialDelay = 300; const minSpinTime = 500; // 最终控制Spinner显示的流 const showSpinner$ = isLoading$.pipe( distinctUntilChanged(), // 过滤重复状态 switchMap(isLoading => { if (isLoading) { // 当开始加载时,先等待initialDelay return timer(initialDelay).pipe( switchMap(() => { // 过了initialDelay,现在要显示Spinner,同时监听两个事件: // 1. minSpinTime到了,允许隐藏 // 2. isLoading变为false,准备隐藏 const minSpinTimer$ = timer(minSpinTime); const loadingStopped$ = isLoading$.pipe(filter(status => !status)); return race(minSpinTimer$, loadingStopped$).pipe( map(() => false), // 不管哪个事件先到,最终都要隐藏 startWith(true), // 先发出true,让Spinner显示 ); }), startWith(false) // 等待initialDelay期间,Spinner不显示 ); } else { // 直接发出false,隐藏Spinner(如果还没显示的话) return of(false); } }) );
对应三个场景的逻辑验证
isLoading在initialDelay前设为false:switchMap会在isLoading变为false时,终止之前等待initialDelay的流,所以showSpinner$始终不会发出true,Spinner永不显示。isLoading在initialDelay后但minSpinTime前设为false:此时已经过了initialDelay,Spinner已经显示,race会等到minSpinTimer$触发后才发出false,保证Spinner显示满minSpinTime。isLoading在initialDelay + minSpinTime之后设为false:race会先捕捉到loadingStopped$事件,立刻发出false,Spinner同步隐藏。
这样就完美覆盖了你所有的需求啦!
内容的提问来源于stack exchange,提问作者swyx
相关产品推荐
相关产品推荐

