我正在尝试学习 Rxjs,但我看到了一些我没有预料到的行为。下面列出了有问题的 javascript 代码
function updateText(css_link, observable){
observable.subscribe(x => {
const container = document.querySelector(css_link);
container.textContent = `${x}`;
});
}
function log(observable) {
observable.subscribe(i => {
console.log(i);
});
}
let source = Rx.Observable.timer(0, 1000)
.map(() => {return {value: Math.random()}});
let double = source
.map(x => {return {value: x.value * 2}});
let diff = source
.pairwise()
.map(a => JSON.stringify(a));
updateText("#source", source.map(x => x.value));
updateText("#double", source.map(x => x.value));
updateText("#diff", diff);
事实证明,double
流的输出是新随机数的 double 值,而不是来自source
的随机数。当查看 diff
的输出时,我再次感觉到随机数是在 source
、double
和 diff< 中独立生成的
。
我正在学习 Rxjs,我可能漏掉了一点。我认为这些流是不可变的,但它们确实相互依赖。
您可以在 jsbin 上找到此代码的一个版本一些正在更新的 html。
最佳答案
这是因为每次您订阅时,您都在创建一个带有新源 Observable 的新链。这意味着 source
、double
和 diff
每个都有自己的计时器。
您可以通过在每次创建新计时器时向控制台打印一条消息来证明这是真的:
let source = Rx.Observable.defer(() => {
console.log('new source');
return Rx.Observable.timer(0, 1000)
.map(() => {return {value: Math.random()}});
});
现在您将在控制台中看到三个消息 “new source”
。
如果你想共享单个源 Observable,你可以使用多播,特别是 share()
运算符。
let source = Rx.Observable.defer(() => {
console.log('new source');
return Rx.Observable.timer(0, 1000)
.map(() => {return {value: Math.random()}});
}).share();
现在您只会在控制台中看到一个“new source”
,它应该会如您所愿地工作。
所以你的源代码看起来像这样:
let source = Rx.Observable.timer(0, 1000)
.map(() => {return {value: Math.random()}})
.share();
关于javascript - RxJS 不能与 Math.random() 配合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42655505/