RxJS 相当于 `Bacon.when()` 的属性(被采样但不是同步模式的一部分)
RxJS equivalent of `Bacon.when()` with properties (which are sampled but not part of the synchronization pattern)
考虑以下 Bacon.js 代码示例(大致基于 the code here, uses bacon.model & bacon.jquery):
<input id="total" type="text" placeholder="total">
/
<input id="quantity" type="text" placeholder="quantity" value="1">
=
<span id="price"></span>
<script>
var $total = Bacon.$.textFieldValue($("#total")).changes();
var quantity = Bacon.$.textFieldValue($("#quantity"));
var price = Bacon.when(
[$total, quantity], function(x,y) { return x/y; }
).toProperty(0);
price.onValue(function (p) {
$('#price').text(p);
});
</script>
这里发生的是流 $total
和 属性 quantity
连接成一个 属性 price
。 $total
和 quantity
都从文本输入字段获取输入,但只有 $total
提示 price
进行更新。 (即 quantity
被采样但不是同步模式的一部分。)
我正在尝试使用 RxJS 而不是 Bacon.js 来实现同样的行为,但我所能想到的只是超级丑陋的解决方案。我想我一定是忽略了什么……?
到目前为止我最好的一张照片(行为不尽相同,但你明白了):
var totalChange = Rx.Observable.fromEvent($('#total'), 'input');
var totalValue = totalChange.map(function () {
return parseInt($('#total').val(), 10);
});
var quantityValue = totalChange.map(function () {
return parseInt($('#quantity').val(), 10);
});
var price = Rx.Observable.zip(
totalValue,
quantityValue,
function (x,y) {
return x/y;
}
);
price.subscribe(function (p) {
$('#price').text(p);
});
因为 combineLatest
或 zip
都没有在直接表示两个文本字段的可观察对象上提供所需的行为,所以我能想到的就是根据总计的文本字段。哪个可行,但感觉很牵强。
对替代方法有什么建议吗?
编辑:combineLatest 似乎相当于培根的 when。
我想也许您正想做这样的事情?
var totalChange = Rx.Observable.fromEvent($('#total'), 'input');
var totalValue = totalChange.map(function () {
return parseInt($('#total').val(), 10);
});
var quantityValue = totalChange.map(function () {
return parseInt($('#quantity').val(), 10);
});
Observable.combineLatest(totalValue, quantityValue, function(total, quantity) {
return total / quantity;
});
不幸的是,这是我能想到的最漂亮的回答你问题的精神。
但实际上,举个例子,您只需这样做:
var price = totalChange.map(function() {
return parseInt($('#total').val(), 10) / parseInt($('#quantity').val(), 10);
});
使用最近添加的 withLatestFrom
而不是 combineLatest
。
var price = totalValue.withLatestFrom(quantityValue, (x,y) => x/y);
比较他们的图表:
编辑:我刚刚意识到这个解决方案位于 Ben Lesh 答案的底部。我将把它留在这里只是为了更冗长的解释。
如果一个变量不是反应性的,有时最简单的解决方案就是承认这一点而不试图对其做出反应。
由于 quantity
不可观察,任何使其可观察然后组合 2 个可观察流的尝试都会让人觉得很老套。
相反,我只是拥抱它的不可观察性,并在 total
变化时使用 map
阅读它:
var totalChange = Rx.Observable.fromEvent($('#total'), 'input');
var totalValue = totalChange.map(function () {
return parseInt($('#total').val(), 10);
});
var price = totalValue.map(function (total) {
var quantity = parseInt($('#quantity').val(), 10);
return total / quantity;
});
price.subscribe(function (p) {
$('#price').text(p);
});
// or, more succinctly with a single map operation:
var totalChange = Rx.Observable.fromEvent($('#total'), 'input');
var price = totalChange.map(function () {
var total = parseInt($('#total').val(), 10);
var quantity = parseInt($('#quantity').val(), 10);
return total / quantity;
});
price.subscribe(function (p) {
$('#price').text(p);
});
考虑以下 Bacon.js 代码示例(大致基于 the code here, uses bacon.model & bacon.jquery):
<input id="total" type="text" placeholder="total">
/
<input id="quantity" type="text" placeholder="quantity" value="1">
=
<span id="price"></span>
<script>
var $total = Bacon.$.textFieldValue($("#total")).changes();
var quantity = Bacon.$.textFieldValue($("#quantity"));
var price = Bacon.when(
[$total, quantity], function(x,y) { return x/y; }
).toProperty(0);
price.onValue(function (p) {
$('#price').text(p);
});
</script>
这里发生的是流 $total
和 属性 quantity
连接成一个 属性 price
。 $total
和 quantity
都从文本输入字段获取输入,但只有 $total
提示 price
进行更新。 (即 quantity
被采样但不是同步模式的一部分。)
我正在尝试使用 RxJS 而不是 Bacon.js 来实现同样的行为,但我所能想到的只是超级丑陋的解决方案。我想我一定是忽略了什么……?
到目前为止我最好的一张照片(行为不尽相同,但你明白了):
var totalChange = Rx.Observable.fromEvent($('#total'), 'input');
var totalValue = totalChange.map(function () {
return parseInt($('#total').val(), 10);
});
var quantityValue = totalChange.map(function () {
return parseInt($('#quantity').val(), 10);
});
var price = Rx.Observable.zip(
totalValue,
quantityValue,
function (x,y) {
return x/y;
}
);
price.subscribe(function (p) {
$('#price').text(p);
});
因为 combineLatest
或 zip
都没有在直接表示两个文本字段的可观察对象上提供所需的行为,所以我能想到的就是根据总计的文本字段。哪个可行,但感觉很牵强。
对替代方法有什么建议吗?
编辑:combineLatest 似乎相当于培根的 when。
我想也许您正想做这样的事情?
var totalChange = Rx.Observable.fromEvent($('#total'), 'input');
var totalValue = totalChange.map(function () {
return parseInt($('#total').val(), 10);
});
var quantityValue = totalChange.map(function () {
return parseInt($('#quantity').val(), 10);
});
Observable.combineLatest(totalValue, quantityValue, function(total, quantity) {
return total / quantity;
});
不幸的是,这是我能想到的最漂亮的回答你问题的精神。
但实际上,举个例子,您只需这样做:
var price = totalChange.map(function() {
return parseInt($('#total').val(), 10) / parseInt($('#quantity').val(), 10);
});
使用最近添加的 withLatestFrom
而不是 combineLatest
。
var price = totalValue.withLatestFrom(quantityValue, (x,y) => x/y);
比较他们的图表:
编辑:我刚刚意识到这个解决方案位于 Ben Lesh 答案的底部。我将把它留在这里只是为了更冗长的解释。
如果一个变量不是反应性的,有时最简单的解决方案就是承认这一点而不试图对其做出反应。
由于 quantity
不可观察,任何使其可观察然后组合 2 个可观察流的尝试都会让人觉得很老套。
相反,我只是拥抱它的不可观察性,并在 total
变化时使用 map
阅读它:
var totalChange = Rx.Observable.fromEvent($('#total'), 'input');
var totalValue = totalChange.map(function () {
return parseInt($('#total').val(), 10);
});
var price = totalValue.map(function (total) {
var quantity = parseInt($('#quantity').val(), 10);
return total / quantity;
});
price.subscribe(function (p) {
$('#price').text(p);
});
// or, more succinctly with a single map operation:
var totalChange = Rx.Observable.fromEvent($('#total'), 'input');
var price = totalChange.map(function () {
var total = parseInt($('#total').val(), 10);
var quantity = parseInt($('#quantity').val(), 10);
return total / quantity;
});
price.subscribe(function (p) {
$('#price').text(p);
});