2017-03-07 31 views
1

不能很好地玩我想学习Rxjs,我看到一些我没想到的行为。有问题的JavaScript代码如下RxJS与Math.random()

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流的输出是新的随机数,而不是从source附带的随机数字双重价值。在查看diff的输出时,我再次得到这样的印象:随机数在source,doublediff中独立生成。

我正在学习Rxjs,我可能会错过一个观点。我认为这些流是不可改变的,但它们确实相互依赖。

你可以在jsbin上找到这个代码的一个版本,它具有一些正在更新的html。

回答

2

这是因为你每次订阅你正在用一个新的源Observable创建一个新的链。这意味着source,doublediff每个人都有自己的计时器。

你可以看到,这是通过打印一个消息到控制台每次你创建一个新的计时器时间真:

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(); 

您更新演示:https://jsbin.com/guyigox/3/edit?js,console,output