• combineLatest
    • 签名: combineLatest(observables: ...Observable, project: function): Observable
  • 当任意 observable 发出值时,发出每个 observable 的最新值。
    • 为什么使用 combineLatest
    • 示例
      • 示例 1: 组合3个定时发送的 observables
      • 示例 2: 使用 projection 函数的 combineLatest
      • 示例 3: 组合2个按钮的事件
        • HTML
  • 其他资源

    combineLatest

    签名: combineLatest(observables: ...Observable, project: function): Observable

    当任意 observable 发出值时,发出每个 observable 的最新值。


    :bulb: 此操作符可以既有静态方法,又有实例方法!

    :bulb: 当源 observable 完成时,可以使用 combineAll 来应用 combineLatest 以发出 observables !


    为什么使用 combineLatest

    当有多个长期活动的 observables 且它们依靠彼此来进行一些计算或决定时,此操作符是最适合的。示例 3可作为基础示例演示,来自多个按钮的事件被组合在一起,以生成每个按钮的计数和总体总数,RxJS 文档中的 combineLatest 操作符的示例 BMI 计算 也可作为示例。

    注意,combineLatest 直到每个 observable 都至少发出一个值后才会发出初始值。这和 withLatestFrom 的行为是一致的,这常常会成为陷阱,既没有输出,也不报错,但是一个(或多个)内部 observables 可能无法正常工作,或者订阅延迟。

    最后,如果你只需要 observables 发出一个值,或只需要它们完成前的最新值时,forkJoin 会是更好的选择。

    combineLatest - 图3

    示例

    ( 示例测试 )

    示例 1: 组合3个定时发送的 observables

    ( StackBlitz |
    jsBin |
    jsFiddle )

    1. import { timer } from 'rxjs/observable/timer';
    2. import { combineLatest } from 'rxjs/observable/combineLatest';
    3. // timerOne 在1秒时发出第一个值,然后每4秒发送一次
    4. const timerOne = timer(1000, 4000);
    5. // timerTwo 在2秒时发出第一个值,然后每4秒发送一次
    6. const timerTwo = timer(2000, 4000);
    7. // timerThree 在3秒时发出第一个值,然后每4秒发送一次
    8. const timerThree = timer(3000, 4000);
    9. // 当一个 timer 发出值时,将每个 timer 的最新值作为一个数组发出
    10. const combined = combineLatest(timerOne, timerTwo, timerThree);
    11. const subscribe = combined.subscribe(latestValues => {
    12. // 从 timerValOne、timerValTwo 和 timerValThree 中获取最新发出的值
    13. const [timerValOne, timerValTwo, timerValThree] = latestValues;
    14. /*
    15. 示例:
    16. timerOne first tick: 'Timer One Latest: 1, Timer Two Latest:0, Timer Three Latest: 0
    17. timerTwo first tick: 'Timer One Latest: 1, Timer Two Latest:1, Timer Three Latest: 0
    18. timerThree first tick: 'Timer One Latest: 1, Timer Two Latest:1, Timer Three Latest: 1
    19. */
    20. console.log(
    21. `Timer One Latest: ${timerValOne},
    22. Timer Two Latest: ${timerValTwo},
    23. Timer Three Latest: ${timerValThree}`
    24. );
    25. }
    26. );
    示例 2: 使用 projection 函数的 combineLatest

    ( StackBlitz |
    jsBin |
    jsFiddle )

    1. import { timer } from 'rxjs/observable/timer';
    2. import { combineLatest } from 'rxjs/observable/combineLatest';
    3. // timerOne 在1秒时发出第一个值,然后每4秒发送一次
    4. const timerOne = timer(1000, 4000);
    5. // timerTwo 在2秒时发出第一个值,然后每4秒发送一次
    6. const timerTwo = timer(2000, 4000);
    7. // timerThree 在3秒时发出第一个值,然后每4秒发送一次
    8. const timerThree = timer(3000, 4000);
    9. // combineLatest 还接收一个可选的 projection 函数
    10. const combinedProject = combineLatest(
    11. timerOne,
    12. timerTwo,
    13. timerThree,
    14. (one, two, three) => {
    15. return `Timer One (Proj) Latest: ${one},
    16. Timer Two (Proj) Latest: ${two},
    17. Timer Three (Proj) Latest: ${three}`;
    18. }
    19. );
    20. // 输出值
    21. const subscribe = combinedProject.subscribe(latestValuesProject =>
    22. console.log(latestValuesProject)
    23. );
    示例 3: 组合2个按钮的事件

    ( StackBlitz |
    jsBin |
    jsFiddle )

    1. import { mapTo, startWith, scan, tap, map } from 'rxjs/operators';
    2. import { fromEvent } from 'rxjs/observable/fromEvent';
    3. import { combineLatest } from 'rxjs/observable/combineLatest';
    4. // 用来设置 HTML 的辅助函数
    5. const setHtml = id => val => (document.getElementById(id).innerHTML = val);
    6. const addOneClick$ = id =>
    7. fromEvent(document.getElementById(id), 'click').pipe(
    8. // 将每次点击映射成1
    9. mapTo(1),
    10. startWith(0),
    11. // 追踪运行中的总数
    12. scan((acc, curr) => acc + curr),
    13. // 为适当的元素设置 HTML
    14. tap(setHtml(`${id}Total`))
    15. );
    16. const combineTotal$ = combineLatest(addOneClick$('red'), addOneClick$('black'))
    17. .pipe(map(([val1, val2]) => val1 + val2))
    18. .subscribe(setHtml('total'));
    HTML
    1. <div>
    2. <button id='red'>Red</button>
    3. <button id='black'>Black</button>
    4. </div>
    5. <div>Red: <span id="redTotal"></span> </div>
    6. <div>Black: <span id="blackTotal"></span> </div>
    7. <div>Total: <span id="total"></span> </div>

    其他资源

    • combineLatest :newspaper: - 官方文档
    • 使用 combineLatest 组合流 :video_camera: :dollar: - John Linquist
    • 组合操作符: combineLatest :video_camera: :dollar: - André Staltz

    :file_folder: 源码: https://github.com/ReactiveX/rxjs/blob/master/src/internal/operators/combineLatest.ts