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$totalquantity 都从文本输入字段获取输入,但只有 $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);
});

因为 combineLatestzip 都没有在直接表示两个文本字段的可观察对象上提供所需的行为,所以我能想到的就是根据总计的文本字段。哪个可行,但感觉很牵强。

对替代方法有什么建议吗?

编辑: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);
});