【问题标题】:Temporarily accumulate objects depending on the state of a different stream根据不同流的状态临时累积对象
【发布时间】:2014-08-15 18:43:53
【问题描述】:

我一直在尝试自学 FRP(特别是 bacon.js),方法是先深入研究一个新项目。我自己已经走了很远,但最近遇到了一个我似乎无法解决的问题:

我有一个带有一组可点击对象的界面。单击对象时,该对象的详细信息将加载到右侧的面板中。

我需要的是能够选择多个,将这些对象累积到一个数组中,并在选择多个时显示“批量操作”面板。

到目前为止我有:

  • 代表当前 UI 模式的 SelectMultiple 布尔属性
  • 保存当前选定对象的 CurrentObject 流

我已经有点接近了:

var SelectedObjects = CurrentObject.filter(SelectMultiple).skipDuplicates().scan([], function(a,b){
    return a.concat([b]);
};

有几个问题:

  1. SelectedObjects 的值表示选中的对象 一直,当 SelectMultiple 状态改变时它不会重置。
  2. SelectObjects 的值不包括原来的 CurrentObject(当然因为扫描累加器种子是 空数组,而不是 CurrentObject 的当前值)。

我希望直接使用属性的当前值这一事实似乎暗示这里存在一个基本问题。我有一个想法,答案涉及到翻盖地图和每次 SelectMultiple 更改时产生一个新流,将选定的订单汇集到这个新流中并累积,但我不太清楚应该是什么样子。

当然还有一个额外的问题,skipDuplicates 只会跳过连续的重复。我可能可以自己解决这个问题,但解决该问题的解决方案将是理想的。

任何建议将不胜感激!

【问题讨论】:

    标签: javascript frp bacon.js


    【解决方案1】:

    这可能有效(咖啡脚本):

    var selectMultiple # Property[Boolean] - whether in multiselect mode
    var selectedObject # Property[Object] - latest selected object
    var selectedObjects = selectMultiple.flatMapLatest((multiple) ->
      if !multiple
        selectedObject.map((obj) -> [obj])
      else
        selectedObject.scan([], (xs, x) ->
          xs.concat(x)
        )
    ).toProperty()
    

    selectMultiple 标志的每个值上,我们都会启动一个新的流,它要么只跟踪当前的单个选择,要么从单个选择开始累积,在它们被选中时添加项目。它不支持通过切换取消选择,但可以直接添加到 scan 部分。

    【讨论】:

      【解决方案2】:

      好的,我想出了一个解决方案。我意识到我可以使用动态大小的slidingWindow 组合器。我在Implementing Snake in Bacon.js教程中找到了答案的依据。

      当我尝试直接添加到 Bacon 原型时​​出现错误(如教程中所述),所以我只创建了一个函数来观察流和一个布尔值来确定它是否应该捕获值:

      slidingWindowWhile = function(sourceStream, toTakeOrNotToTake) {
          return new Bacon.EventStream(function(sink){
              var buf = [];
              var take = false;
      
              sourceStream.onValue(function(x){
                  if (! take) {
                      buf = [];
                  }
                  buf.push(x);
                  sink(new Bacon.Next(buf));
              });
      
              toTakeOrNotToTake.onValue(function(v){
                  take = v;
              });
          });
      };
      

      似乎应该有一种方法可以在不使用局部变量来跟踪状态的情况下做到这一点,但至少这个解决方案被很好地封装了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-24
        • 2016-01-27
        • 2015-08-19
        • 2022-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-25
        相关资源
        最近更新 更多