Rxjs - Operators - WithLatestFrom

Signature

public withLatestFrom(other: Observable, project: Function): Observable

当source流发出新value的时候,去和 参数流的最新值做一些整合操作
这是和combineLast最大的不同.

combineLast 是无论source流还是参数流,任何一个有新value就会发出新的整合值
这个withLatestFrom的触发条件是source流有新value

Sample

来自Cycle.js

const {Observable} = Rx;
const {div, span, input, makeDOMDriver} = CycleDOM;

function LabeledSlider(sources) {
const initialValue$ = sources.props$
.map(props => props.initial)
.first();

const newValue$ = sources.DOM
.select('.slider')
.events('input')
.map(ev => ev.target.value);

const value$ = initialValue$.concat(newValue$);

const vtree$ = Observable.combineLatest(sources.props$, value$,
(props, value) =>
div('.labeled-slider', [
span('.label',
props.label + ' ' + value + props.unit
),
input('.slider', {
type: 'range', min: props.min, max: props.max, value: value
})
])
);

const sinks = {
DOM: vtree$,
value$: value$,
};
return sinks;
}

function main(sources) {
const props$ = Observable.of({
label: 'Radius', unit: 'kg', min: 20, initial: 50, max: 80
});
const childSources = {DOM: sources.DOM, props$};
const labeledSlider = LabeledSlider(childSources);
const childVTree$ = labeledSlider.DOM;
const childValue$ = labeledSlider.value$;

const vtree$ = childVTree$.withLatestFrom(childValue$,
(childVTree, value) =>
div([
childVTree,
div({style: {
backgroundColor: '#58D3D8',
width: String(value) + 'px',
height: String(value) + 'px',
borderRadius: String(value * 0.5) + 'px'
}})
])
);
return {
DOM: vtree$
};
}

Cycle.run(main, {
props$: () => Observable.of({
label: 'Weight', unit: 'kg', min: 40, initial: 70, max: 140
}),
DOM: makeDOMDriver('#app')
});

const vtree$ = childVTree$.withLatestFrom(childValue$,
(childVTree, value) =>
div([
childVTree,
div({style: {
backgroundColor: '#58D3D8',
width: String(value) + 'px',
height: String(value) + 'px',
borderRadius: String(value * 0.5) + 'px'
}})
])
);
  • 主流是childVTree$
  • 子流childValue$

只有当有新的childVTree,也就是重新render组件的时候,才去和最新的childValue 整合成新的父组件