zoukankan      html  css  js  c++  java
  • [RxJS] Loading Spinner with busyDelayMs & busyMinDurationMs api

    const { merge, timer, Subject, combineLatest } = require("rxjs");
    const {
      tap,
      mapTo,
      skip,
      filter,
      startWith,
      takeUntil,
      switchMap,
    } = require("rxjs/operators");
    
    const DELAY = 500;
    const MIN_DURATION = 1200;
    
    const taskStartSubject = new Subject();
    const taskStart = taskStartSubject.asObservable();
    const taskEndSubject = new Subject();
    const taskEnd = taskEndSubject.asObservable();
    const busyDelayTimer = timer(DELAY);
    const busyMinDurationTimer = timer(MIN_DURATION + DELAY);
    const busyDelayTimerStart = taskStart.pipe(switchMap(() => busyDelayTimer));
    const busyDelayTimerEnd = busyDelayTimerStart.pipe(takeUntil(taskEnd));
    const emitOnTaskEnd = taskEnd.pipe(mapTo(1));
    const emitOnDelayTimerEnd = busyDelayTimerEnd.pipe(mapTo(-1));
    const emitOnMinDurationEnd = busyMinDurationTimer.pipe(mapTo(-1));
    
    ////////////// start/////////////////
    
    const raceBetweenTaskAndDelay = combineLatest([
      emitOnTaskEnd.pipe(startWith(null)),
      emitOnDelayTimerEnd.pipe(startWith(null)),
    ]).pipe(skip(1));
    const taskEndBeforeDelay = raceBetweenTaskAndDelay.pipe(
      filter(([taskEndFirst, timerEndFirst]) => {
        return taskEndFirst === 1 && timerEndFirst === null;
      })
    );
    const shouldNotShowSpinner = taskEndBeforeDelay.pipe(mapTo(false));
    const taskEndAfterTimeout = raceBetweenTaskAndDelay.pipe(
      filter(([taskEndFirst, timerEndFirst]) => {
        return taskEndFirst === null && timerEndFirst === -1;
      })
    );
    const shouldShowSpinner = taskEndAfterTimeout.pipe(mapTo(true));
    const showSpinner = shouldShowSpinner.pipe(
      tap(() => {
        console.timeLog("spinner");
        console.log("show");
      })
    );
    
    /////////////// end ///////////////
    
    const raceBetweenTaskAndMinDuration = combineLatest([
      emitOnTaskEnd.pipe(startWith(null)),
      emitOnMinDurationEnd.pipe(startWith(null)),
    ]).pipe(skip(1));
    const hideSpinnerUntilMinDurationEnd = raceBetweenTaskAndMinDuration.pipe(
      filter(([taskEndFirst, timerEndFirst]) => {
        return taskEndFirst === 1 && timerEndFirst === null;
      })
    );
    const hideSpinnerAfterTimerAndTaskEnd = raceBetweenTaskAndMinDuration.pipe(
      filter(([taskEndFirst, timerEndFirst]) => {
        return taskEndFirst === 1 && timerEndFirst === -1;
      })
    );
    const hideSpinner = merge(
      // case 1: should not show spinner at all
      shouldNotShowSpinner,
      // case 2: task end, but wait until min duration timer ends
      combineLatest([hideSpinnerUntilMinDurationEnd, emitOnMinDurationEnd]),
      // case 3: task takes a long time, wait unitl its end
      hideSpinnerAfterTimerAndTaskEnd
    ).pipe(
      tap(() => {
        console.timeLog("spinner");
        console.log("hide");
      })
    );
    const Spinner = showSpinner.pipe(takeUntil(hideSpinner));
    
    // test
    Spinner.subscribe();
    
    console.log("task start");
    console.time("spinner");
    taskStartSubject.next();
    
    // Case 1: Should not show spinner
    
    setTimeout(() => {
      taskEndSubject.next();
    }, 50);
    
    // Case 2: Should show spinner when busyMinDurationMs end
    /*
    setTimeout(() => {
      taskEndSubject.next();
    }, 600);
    */
    // Case 3: Should show spinner until task ends
    /*
    setTimeout(() => {
      taskEndSubject.next();
    }, 2000);
    */
  • 相关阅读:
    史上最全web.xml配置文件元素详解
    SpringMVC后台接收list类型的数据的实现方式
    史上最全的maven的pom.xml文件详解
    阿里菜鸟同学迟到的2018年个人总结(文末彩蛋)
    可以落地的DDD到底长什么样?
    欠的债,这一次都还给你们
    主流分布式架构的风流韵事...
    分布式架构的前世今生...
    分布式架构之美~
    征服诱人的Vagrant!
  • 原文地址:https://www.cnblogs.com/Answer1215/p/12908045.html
Copyright © 2011-2022 走看看