🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# combineAll 通过等待外部Observable完成,然后应用`combineLatest`,将高阶Observable转换成一阶Observable。 **方法签名**: ``` public combineAll(project: function): Observable ``` **示例一**: ```javascript var source = Rx.Observable.interval(1000).take(2); var example = source .map(val => Rx.Observable .interval(1000) .map(i => `${val}: ${i}`) .take(5) ); var combined = example.combineAll(); combined.subscribe(console.log); ``` **结果**: ``` ["0: 0", "1: 0"] ["0: 1", "1: 0"] ["0: 1", "1: 1"] ["0: 2", "1: 1"] ["0: 2", "1: 2"] ["0: 3", "1: 2"] ["0: 3", "1: 3"] ["0: 4", "1: 3"] ["0: 4", "1: 4"] ``` **分析**:在调用`combineAll`时,内部Observable(`source`执行`map`时返回的)会等待外部Obserevable完成,这里当`source`发出值`0`, `1`后,开始执行内部Observable。由于外部发出了2个值,所以会得到一个长度为2的数组,当`val`值为`0`时并执行完`take`后我们得到[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]这样一个结果,然后`val`值为`1`时,得到[1,0], [1,1], [1,2], [1,3], [1,4]。然后对两次获得的结果执行`combineLatest`。 整个过程可以参照分析`combineLatest`时同样的方式来描述,直接根据下面的图得到结果 ![](https://box.kancloud.cn/a76c432b4959359e7539fe889a410aee_530x211.png) 如果将示例中`soure`这个Observable中的`take`参数值改为`3`, 我们可以绘制下面 这个图。 ![](https://box.kancloud.cn/df3c4a57adb07427922a233f5c3be5dc_527x307.png) 很直观可以得出参与`combineLatest`计算前的3个Observable的结果, 这里假定为`A`, `B`, `C`。那么`A`为 `[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]`,`B`为`[1, 0], [1, 1], [1, 2], [1, 3], [1, 4]`, `C`为`[2, 0], [2, 1], [2, 2], [2, 3], [2, 4]`,然后我们以这些结果值为树节点,顺序构造出上面的分析树。 , 对于节点`0,0`,很显然只有一条路径`[0, 0], [1, 0], [2, 0]`, 对于后面的节点都有3条路径,这里直接给出后面的结果: ``` [0, 1], [1, 0], [2, 0] [0, 1], [1, 1], [2, 0] [0, 1], [1, 1], [2, 1] [0, 2], [1, 1], [2, 1] [0, 2], [1, 2], [2, 1] [0, 2], [1, 2], [2, 2] [0, 3], [1, 2], [2, 2] [0, 3], [1, 3], [2, 2] [0, 3], [1, 3], [2, 3] [0, 4], [1, 4], [2, 3] [0, 4], [1, 4], [2, 4] ``` **示例二** ```javascript var clicks = Rx.Observable.fromEvent(document, 'click'); var higherOrder = clicks.map(ev => Rx.Observable.interval(Math.random()*2000).take(3) ).take(2); var result = higherOrder.combineAll(); result.subscribe(x => console.log(x)); ``` > 注:来自rxjs官网[示例](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-combineAll) 这个例子得到的结果有可能为 ``` [0, 2] [1, 2] [2, 2] ``` 或者: ``` [0, 0] [1, 0] [1, 1] [2, 1] [2, 2] ``` 这是因为传给`Rx.Observable.interval`的参数是一个随机数造成的,我们这里把它的参数直接改成`1000`方便分析结果。此时再次运行,会得到上面的第2个结果,为什么呢? 也许看了这个示例会有所疑问: > 这个例子和示例一很相似,外层Observable发出2个值, 内部Observable发出3个值,结果应该类似`[0, 0], [0, 1]`这种才对呀? 其实,我们注意到鼠标点击事件对象`ev`的值我们并没有使用,由于`combineAll`内部调用`combineLatest`前,`map`函数执行后实际得到两个一样的结果:[0, 1, 2]。既然得到执行`map`过后的结果,采用老办法,见图即可得到结果: ![](https://box.kancloud.cn/c3b85125063187aaa9ca1c84b90d1e56_265x160.png)