使用不可变数据结构的RxJS?

5

我正在学习RxJSKoans,发现一个反复出现的模式,即向结果数组中添加数据,订阅者会推送新值:

var Rx = require('rx'),
    Subject = Rx.Subject

var result = [];
var s1 = new Subject();
s1.subscribe(result.push.bind(result));
s1.onNext('foo');
result;  // ['foo']

这显然是一个不纯的函数;result数组被subscribe改变了。
我看过一些在Github上的小型项目,它们试图使用Immutable.js解决这个问题,但没有一个得到积极维护。
我想知道是否有广泛采用的不可变实现模式,如果没有,为什么?
1个回答

5
我不认为这是一种模式,但由于您可以通过流传递所有内容,因此您也可以传递任何不可变数据结构:

const stream$ = Rx.Subject.create();

stream$
  .map(data => data.set('a', data.get('a') + 1))
  .subscribe(data => console.log(data));

stream$.next(Immutable.Map({ a:1 }));
stream$.next(Immutable.Map({ a:2 }));
<script src="https://npmcdn.com/@reactivex/rxjs@5.0.0-beta.7/dist/global/Rx.umd.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>

此外,没有理由将result作为外部状态。这就是像scan这样的方法存在的原因。我建议你将其用于管理(内部)状态:

const stream$ = Rx.Subject.create();

stream$
  .scan((list, val) => list.push(val), Immutable.List())
  .subscribe(data => console.log(data));

stream$.next('foo');
stream$.next('bar');
<script src="https://npmcdn.com/@reactivex/rxjs@5.0.0-beta.7/dist/global/Rx.umd.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>


2
不过我要提醒的是,一些rxjs运算符使用JavaScript数组而不是List。因此,您必须将扁平化运算符夹在rxjs map运算符内,返回值为data.toJS(),然后再用另一个运算符Immutable.fromJS(data)。不过这种情况并不经常发生。 - Marcus Rådell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接