Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 基于另一个可观测的自定义过滤器的函数反应算子_Javascript_Reactive Programming_Rxjs_Bacon.js - Fatal编程技术网

Javascript 基于另一个可观测的自定义过滤器的函数反应算子

Javascript 基于另一个可观测的自定义过滤器的函数反应算子,javascript,reactive-programming,rxjs,bacon.js,Javascript,Reactive Programming,Rxjs,Bacon.js,为了好玩和学习,我尝试在我的应用程序中使用函数式反应式编程实现一个撤销系统。我有一个状态更改流,需要保存到撤消堆栈中。当用户单击undo时,我从堆栈中获取一个值,并相应地更新应用程序状态 问题在于,此更新本身也会在状态更改流中生成一个事件。所以我想从状态更改中派生另一个流,它的状态在撤销后立即更改 一个简单的图表: states ----S----S----S---- undos -------U----------- save ----S---------S----

为了好玩和学习,我尝试在我的应用程序中使用函数式反应式编程实现一个撤销系统。我有一个状态更改流,需要保存到撤消堆栈中。当用户单击undo时,我从堆栈中获取一个值,并相应地更新应用程序状态

问题在于,此更新本身也会在状态更改流中生成一个事件。所以我想从状态更改中派生另一个流,它的状态在撤销后立即更改

一个简单的图表:

states   ----S----S----S----
undos    -------U-----------     
save     ----S---------S----
第一行是应用程序状态更改流,第二行是由用户触发的撤消事件,第三行是我想要实现和侦听的流,而不是第一个流

在FRP中表达这种意图的最佳方式是什么?

在RxJS中:

var state = Rx.Observable.interval(2000)
  .map(s => ({type:'s', value: s}))
  .take(3);
var undo = Rx.Observable.interval(3000)
  .map(u => ({type:'u', value: u}; }))
  .take(1);

var save = state.merge(undo).scan((prev, curr) =>
  if (prev.type === 'u') {
    return {type: 'removed'};
  } else {
    return curr;
  }
}).filter(x => x.type !== 'removed' && x.type !== 'u');

看这个。诀窍是merge是一个垂直组合器(相对于流图是垂直的),而scan是一个水平组合器。使用这两种方法,首先合并,然后扫描,您可以构建更强大的组合器,就像解决问题的组合器一样。Bacon和Kefir中的解决方案类似。

对于Bacon.js,我将使用函数来维护整个撤销堆栈的属性。这样,我们可以支持多个连续的撤消步骤

var state = Bacon.sequentially(1000, [1,2,3])
var undo = Bacon.later(2500, "undo")

var stateStack = Bacon.update(
[],
state, function(prev, s) { return prev.concat(s) },
undo, function(prev, u) { return prev.slice(0, prev.length - 1) }
)

var currentState = stateStack.changes().map(function(stack) {
  return stack[stack.length-1]
})

stateStack.log()
currentState.log()

但你所在的州看起来会有所不同。如果您向更新添加索引,您将注意到
S1-U1-S0-S2
vs
S1-S2
->即,当您执行撤销1(U1)时,您的状态将有效地更改为状态0(未显示在流#3中),因此您必须在该位置更改该状态,或者显示状态0,并从流#3中删除状态1希望你明白我的意思。我不知道你的意思。请不要过多地讨论撤销功能的逻辑,我主要是在上下文中偶然发现了一个我无法使用流解决的问题。现在,我对撤销方面不太感兴趣,而是对这个特定流场景的一般解决方案感兴趣。如果您想合并两个流,请考虑合并两个数组,即:
[{a:1},{a:2},{x:!0},{a:3},{a:4},{a:5}]。reduce(函数(a,v){if(v.x){a.pop()}else a.push(v);返回a;[])>
yourMergedStream.reduce(函数removePreviousUndo(a,v){/*…*/})
请参阅:比我想象的更简单。我尝试过类似的东西,不知道为什么失败了,但后来我开始发明一些疯狂复杂的东西:-)。