• [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);
    */
  • 相关阅读:
    [hdu4585]离线,并查集
    [hdu4498]离散化,simpson求积分
    nginx防止跳转到内网解决
    docker 导入导出
    java rsa 解密报:javax.crypto.BadPaddingException: Decryption error
    algid parse error, not a sequence错误
    AttributeError: module 'Crypto.PublicKey.RSA' has no attribute 'import_key'
    No module named 'winrandom'。
    centos同步时间
    bean 属性排列顺序
  • 原文地址:https://www.cnblogs.com/Answer1215/p/12908045.html
Copyright © 2020-2023  润新知