• 进度条
    • 示例代码
      • html
  • 使用到的操作符

    进度条

    作者 @barryrowe

    本食谱演示了动态进度条的创建、模拟多个请求的管理,并在每个请求完成后更新总体进度。

    进度条 - 图1

    示例代码

    (
    StackBlitz
    )

    1. import { Observable } from 'rxjs/Observable';
    2. import { of } from 'rxjs/observable/of';
    3. import { empty } from 'rxjs/observable/empty';
    4. import { fromEvent } from 'rxjs/observable/fromEvent';
    5. import { from } from 'rxjs/observable/from';
    6. import {
    7. delay,
    8. switchMapTo,
    9. concatAll,
    10. count,
    11. scan,
    12. withLatestFrom,
    13. share
    14. } from 'rxjs/operators';
    15. const requestOne = of('first').pipe(delay(500));
    16. const requestTwo = of('second').pipe(delay(800));
    17. const requestThree = of('third').pipe(delay(1100));
    18. const requestFour = of('fourth').pipe(delay(1400));
    19. const requestFive = of('fifth').pipe(delay(1700));
    20. const loadButton = document.getElementById('load');
    21. const progressBar = document.getElementById('progress');
    22. const content = document.getElementById('data');
    23. // 请求完成后更新进度条
    24. const updateProgress = progressRatio => {
    25. console.log('Progress Ratio: ', progressRatio);
    26. progressBar.style.width = 100 * progressRatio + '%';
    27. if (progressRatio === 1) {
    28. progressBar.className += ' finished';
    29. } else {
    30. progressBar.className = progressBar.className.replace(' finished', '');
    31. }
    32. };
    33. // 通知更新的简单辅助函数
    34. const updateContent = newContent => {
    35. content.innerHTML += newContent;
    36. };
    37. const displayData = data => {
    38. updateContent(`<div class="content-item">${data}</div>`);
    39. };
    40. // 模拟5个不同时长的请求
    41. const observables: Array<Observable<string>> = [
    42. requestOne,
    43. requestTwo,
    44. requestThree,
    45. requestFour,
    46. requestFive
    47. ];
    48. const array$ = from(observables);
    49. const requests$ = array$.pipe(concatAll());
    50. const clicks$ = fromEvent(loadButton, 'click');
    51. const progress$ = clicks$.pipe(switchMapTo(requests$), share());
    52. const count$ = array$.pipe(count());
    53. const ratio$ = progress$.pipe(
    54. scan(current => current + 1, 0),
    55. withLatestFrom(count$, (current, count) => current / count)
    56. );
    57. clicks$.pipe(switchMapTo(ratio$)).subscribe(updateProgress);
    58. progress$.subscribe(displayData);
    html
    1. <div class="progress-container">
    2. <div class="progress" id="progress"></div>
    3. </div>
    4. <button id="load">
    5. Load Data
    6. </button>
    7. <div id="data">
    8. </div>

    感谢 @johnlinquist 对本示例的帮助!

    使用到的操作符

    • concatAll
    • delay
    • fromEvent
    • from
    • scan
    • share
    • switchMap
    • withLatestFrom