Javascript 如何";“反应”;关于RxJS的数据更改?

Javascript 如何";“反应”;关于RxJS的数据更改?,javascript,rxjs,Javascript,Rxjs,RxJS初学者:我在使用RxJS保存和跟踪数据更改方面有问题。假设我在小视图/小部件中构建我的应用程序,每个视图/小部件都有自己的状态,应该在数据更改时进行操作。我该怎么做 更具体的例子。假设我有一个叫做widget的小部件,widget有一个标题和按钮。如果按钮已单击,则状态应包含标题和信息。从RxJS的文档来看,这似乎是一个很好的起点: var widgetState = new Rx.Subject().startWith({ wasClicked: false, title: '

RxJS初学者:我在使用RxJS保存和跟踪数据更改方面有问题。假设我在小视图/小部件中构建我的应用程序,每个视图/小部件都有自己的状态,应该在数据更改时进行操作。我该怎么做

更具体的例子。假设我有一个叫做
widget
的小部件,
widget
有一个标题和按钮。如果按钮已单击,则状态应包含标题和信息。从RxJS的文档来看,这似乎是一个很好的起点:

var widgetState = new Rx.Subject().startWith({
  wasClicked: false,
  title: 'foo'
});
现在,如果某些数据发生更改,我希望得到通知:

var widgetStateChanges = widgetState.subscribe(function(data) {
  console.log('data: ', data);
  // what do i do with the data here?
  // i would like to merge the new data into the old state
});

widgetStateChanges.onNext({ title: 'bar' });
我听了更改,但不知道如何保存它们。如果发生某些数据更改,我还想做一些特殊的事情。像这样的

widgetStateChanges.filter(function(e) {
  return e.wasClicked;
}).do(function(e) {
  console.log('Do something because was clicked now.');
});

但是我不能过滤订阅(
widgetStateChanges
),只能过滤主题(
widgetState
)。

使用
行为主题来跟踪可观察的状态:

var widgetState = new Rx.BehaviorSubject({ wasClicked: false, title: 'foo' });

// change state, probably in response to UI events
// Note we always set the full state, not just the "delta"
widgetState.onNext({ wasClicked: true, title: 'foo2' });

// example listening to title input field and updating state
// assumes rxjs-jquery
$("#title").onAsObservable("change").subscribe (function (ev) {
    var oldState = widgetState.value;
    var newTitle = $("#title").val();
    // do not mutate the oldState object, instead clone it and change the title
    var newState = $.extend({}, oldState, { title: newTitle });

    // send the update
    widgetState.onNext(newState);
});

// listen to new state values, probably to update your HTML?
widgetState.subscribe(function (newState) { ... });

// listen only when wasClicked is true
widgetState
    .filter(function (s) { return s.wasClicked; })
    .subscribe(function (s) { ... });

这难道不违背FRP的理念吗?有什么原因不能使用
.takeLast
内部
.subscribe
进行合并,然后将结果传输到另一个流,您可以订阅/响应该流?我不确定这是否真的违反FRP,可能是。我对这个话题还是个新手。但我觉得这没问题。它的状态不是很相似吗?这看起来很棒。我可以将此应用于我的用例。一些后续问题:为什么我不应该像
state.value那样改变旧的状态。wasClicked=true;state.onNext(state.value)?缺点是什么?如果每次更改时都克隆旧状态,不会导致垃圾收集问题吗?还有一个元问题:你知道学习RxJS()的好指南吗?一些“指导性”的东西,而不是API文档。(RxJS文档非常适合查找,但可能有点难入门。)我所知道的另一个指南是。将数据视为不可变是一个函数式编程概念,通常用于减少必须执行的线程同步量。当通过可观察流发送数据时,这种不变性的概念也非常有用,因为您并不总是知道下游观察者对所看到的数据做了什么。如果下游观察者保留对数据的引用,并且您在源位置更改了该数据,那么观察者通常会感到困惑。一个简单的方法是:
distinctunitrichanged
操作符保留对先前值的引用,并将其与新值进行比较。如果您对该值进行变异,然后“再次发送”,则会欺骗
distinctunitrichanged
运算符,使其认为该值没有更改。学习将不可变流中的数据视为不可变数据将为您节省大量调试奇怪问题的麻烦,还可以更轻松地编写可观察操作,因为您可以保留引用并知道它们引用的对象不会神秘地改变。您使用的可观察属性的数量通常由您的域模型或所需的事务边界。如果要“分解”复合对象并观察单个特性,可以使用自定义比较器(该比较器仅比较要观察的特性)使用
distinctUntilChanged
。或者使用
map
提取单个属性,后跟
distinctUntilChanged
。视情况而定。如果你想要一个例子,就把它作为一个新问题发布