# combineLatest
组合多个Observables以创建一个Observable, 并根据每个输入的Observable的最新值计算。
**方法签名**:
```
// 静态方法
public static combineLatest(observable1: ObservableInput, observable2: ObservableInput, project: function, scheduler: Scheduler): Observable
// 实例方法
public combineLatest(other: ObservableInput, project: function): Observable
```
> 注意:这个方法可以同时作为Observable的静态方法和实例方法使用
- **示例一:使用实例方法**
```javascript
var source = Rx.Observable.interval(1000).take(3);
var dist = Rx.Observable.interval(1000).take(5);
var r = source.combineLatest(dist, (s, d) => `source: ${s} and dist: ${d}`);
r.subscribe(console.log);
```
- **示例二:使用静态方法**
```javascript
var source = Rx.Observable.interval(1000).take(3);
var dist = Rx.Observable.interval(1000).take(5);
var r = Rx.Observable.combineLatest(source, dist, (s, d) => `source: ${s} and dist: ${d}`)
// or `Rx.Observable.combineLatest([source, dist], (s, d) => `source: ${s} and dist: ${d}`)`
r.subscribe(console.log);
```
上述两个示例的结果都为:
```
source: 0 and dist: 0
source: 1 and dist: 0
source: 1 and dist: 1
source: 2 and dist: 1
source: 2 and dist: 2
source: 2 and dist: 3
source: 2 and dist: 4
```
下面分析一下为什么会得到上述结果 ,以`combineLatest`实例方法为例。每当Observable发出值时,它会从每个Observable收集最新的值组成数组(这里数组长为2),这里`source`发出了3个值`0`, `1`, `2`,`dist`发出了`0`, `1`, `2`, `3`, `4`。
```
source:-- 0 - 1 - 2| --
combineLatest()
dist: -- 0 - 1 - 2 - 3 - 4| --
```
如果`source`和`dist`都发出5个值,那么结果如下:
```
source = 0, dist = [0] # 第1秒
source = 1, dist = [0, 1] # 第2秒
source = 2, dist = [1, 2] # 第3秒
source = 3, dist = [2, 3] # 第4钞
source = 4, dist = [3, 4] # 第5钞
```
由于`source`在3秒过后就停止了,而`dist`还在继续执行,此时dist的值为从`source`结束到`dist` 结束这段区间`dist`最后发出的值,即:
`source = 2, dist = [1, 2, 3, 4] # 第3秒`
**示例三:组合多个Observable**
```javascript
// 1秒过后发出第一个值,然后每隔4秒发出下一个值
var timerOne = Rx.Observable.timer(1000, 4000);
// 2秒过后发出第一个值,然后每隔4秒发出下一个值
var timerTwo = Rx.Observable.timer(2000, 4000);
// 3秒过后发出第一个值,然后每隔4秒发出下一个值
var timerThree = Rx.Observable.timer(3000, 4000);
var combined = Rx.Observable.combineLatest(
timerOne,
timerTwo,
timerThree
);
var subscribe = combined.subscribe(latestValues => {
var [one, two, three] =latestValues;
console.log(`one: ${one}, two: ${two}, three: ${three}`);
});
```
**结果**:
```
one: 0, two: 0, three: 0
one: 1, two: 0, three: 0
one: 1, two: 1, three: 0
one: 1, two: 1, three: 1
one: 2, two: 1, three: 1
one: 2, two: 2, three: 1
one: 2, two: 2, three: 2
one: 3, two: 2, three: 2
one: 3, two: 3, three: 2
one: 3, two: 3, three: 3
one: 4, two: 3, three: 3
one: 4, two: 4, three: 3
one: 4, two: 4, three: 4
one: 5, two: 4, three: 4
one: 5, two: 5, three: 4
one: 5, two: 5, three: 5
// ...
```
下面是一个根据时间顺序所画的一个示例 marble 示例图
![](https://box.kancloud.cn/d30a20a9b5e0c38264ca09887bea6f16_866x160.png)
大家有没有发现这个很像一棵树,如果我们把它的子节点都用线连接起来,会得出什么呢?
![](https://box.kancloud.cn/d02c57a797d18f553868fabb6cb4cf11_866x160.png)
注意:这里我用不同颜色对每一个时间作了区分,首先在`0`节点这颗树,只有一个路径,即: [0, 0, 0], 然后是`1`这棵树,它的路径有,[1, 0, 0], [1, 1, 0], [1, 1, 1], 如果对比上面的结果可以发现,刚好和输出一致。
接着看`2`这棵树,可以直接写出结果[2, 1, 0], [2, 1, 1], [2, 2, 1], [2, 2, 2],但有一点需要注意的是[2, 1, 0]这个路径是不合法的,因为它不属于最近一次发出的值,所以`3`这棵树的结果不包括[3, 2, 1]路径,`4`这棵树不包括[4, 3, 2]。
反过来我们用这种方式来分析示例一和二的结果,就一目了然了。
![](https://box.kancloud.cn/7ab24d5e6a6a4e36f9756035637f6d3a_357x145.png)
直接可以看出结果:[0, 0], [1, 0], [1, 1], [2, 1], [2, 2], [2, 3], [2, 4]
- 说明
- angular 1.x
- ngModelController
- ngOptions
- ngModelOptions
- lifecycle
- directive
- angular 2
- @angular/forms
- 类
- AbstractControl
- AbstractControlDirective
- AbstractFormGroupDirective
- FormControl
- FormArray
- FormBuilder
- FormGroup
- NgControl
- 接口
- controlValueAccessor
- 指令
- DefaultValueAccessor
- Angular 2 生命周期
- OnInit
- DoCheck
- @angular/router
- 配置
- Routes
- 指令
- RouterOutlet
- RouterLink
- 接口
- ActivatedRoute
- UrlTree
- NavigationExtras
- ActivatedRouteSnapshot
- RouterStateSnapshot
- 类
- UrlSegment
- UrlSegmentGroup
- UrlSerializer
- DefaultUrlSerializer
- Router
- bug记得
- @angular/http
- 类
- Http
- Body
- Response
- ResponseOptions
- Header
- Request
- RequestOptions
- URLSearchParams
- @angular/core
- decorator
- Component-decorator
- animation
- DI
- linker
- TemplateRef
- ElementRef
- EmbeddedViewRef
- ViewRef
- ViewContainerRef
- Query
- ComponentFactory
- ComponentRef
- Renderer
- change_detection
- KeyValueDiffers
- IterableDiffers
- ChangeDetectorRef
- ChangeDetectionStrategy
- Zone
- ngZone
- @angular/common
- 指令
- NgTemplateOutlet
- QueryList
- bootstrap4
- card
- form
- 重点关注博客
- 学习过的文章
- 笔记
- Angular 2 双向绑定
- 将字符串解析成DOM
- rx相关
- operators
- combineLatest
- combineAll
- concat(All, Map, *MapTo)
- 背压(backpressure)
- js事件keycode对应表
- 装饰器
- 有用的代码摘录
- 日期操作
- 数量操作
- 字符操作
- rxjs问题
- 小示例
- h5面试准备
- react
- 开发遇到的问题