[英]RxJS does not play nice with Math.random()
I am trying to learn Rxjs and I am seeing some behaviour that I did not expect. 我正在尝试学习Rxjs,并且看到了一些我没有想到的行为。 The javascript code in question is listed below 有问题的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);
It turns out that the output of the double
stream are double values of new random numbers, not the random numbers that came from source
. 结果表明double
流的输出是新随机数的double值,而不是source
的随机数。 When looking at the output of diff
I again get the impression that the random numbers are generated independantly in source
, double
and diff
. 当查看diff
的输出时,我再次得到以下印象:随机数是分别在source
, double
和diff
独立生成的。
I am learning Rxjs and I may be missing a point. 我正在学习Rxjs,可能遗漏了一点。 I thought that these streams are immutable but that they do depend on one another. 我认为这些流是不可变的,但是它们确实彼此依赖。
You can find a version of this code on jsbin with some html that is getting updated. 您可以在jsbin上找到此代码的版本, 并带有一些正在更新的html。
This is because every time you subscribe you're creating a new chain with a new source Observable. 这是因为每次订阅时,您都在使用新的Observable源创建一个新链。 This means source
, double
and diff
each one of them has its own timer. 这意味着source
, double
和diff
每个都有自己的计时器。
You can see that this is true by printing a message to console every time you're creating a new timer: 您可以在每次创建新计时器时向控制台打印一条消息,以查看是否正确:
let source = Rx.Observable.defer(() => {
console.log('new source');
return Rx.Observable.timer(0, 1000)
.map(() => {return {value: Math.random()}});
});
Now you'll see three messages "new source"
in console. 现在,您将在控制台中看到三则消息"new source"
。
If you want to share a single source Observable you can use multicasting and in particular the share()
operator. 如果要共享一个可观察的源,则可以使用多播,尤其是share()
运算符。
let source = Rx.Observable.defer(() => {
console.log('new source');
return Rx.Observable.timer(0, 1000)
.map(() => {return {value: Math.random()}});
}).share();
Now you'll see only one "new source"
in console and it should work as you expect. 现在,您将在控制台中仅看到一个"new source"
,它应该可以按预期工作。
So your source can look like this: 因此,您的来源可能如下所示:
let source = Rx.Observable.timer(0, 1000)
.map(() => {return {value: Math.random()}})
.share();
Your updated demo: https://jsbin.com/guyigox/3/edit?js,console,output 您更新的演示: https : //jsbin.com/guyigox/3/edit?js,控制台,输出
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.