我试图找出RxJS模式来声明我的"订阅"这样他们就按顺序执行。
以下是我所处的情况:
var flag = false;
// Stream that non-deterministically emits `true` when flag is true
var random$ = Rx.Observable.interval(1000)
.map(() => setFlagToRandomTrueOrFalse())
.filter(x => x)
.first();
// How can I declare my "subscribes" so that the console.logs happen in order?
var sub1 = random$.subscribe(() => console.log(1), console.log, resetFlagToFalse);
var sub2 = random$.subscribe(() => console.log(2), console.log, resetFlagToFalse);
function setFlagToRandomTrueOrFalse() {
flag = flag || !!Math.floor(Math.random() * 2);
return flag;
}
function resetFlagToFalse() { flag = false; }
由于1
的异步性质,目前按随机顺序打印2
和.subscribe
。
此外,这些"订阅"的正确名称是什么?这里总RxJS noob。
答案 0 :(得分:2)
eeerr我不确定你观察到的顺序是因为subscribe
的异步性质。
首先,正如目前所写,random$
是一个冷源,即尚未订阅的生产者。每次订阅时,该制作人都会开始制作。这意味着在这里,你将启动生产者两次,所以你将为每个生成两个不同的随机值,所以日志将在不同的时间显示,因为你没有订阅相同的值序列,即使它看起来非常喜欢。
关于冷流和热流之间区别的更清楚的描述是Hot and Cold observables : are there 'hot' and 'cold' operators?。花费尽可能多的时间来理解这一点,因为在您开始使用Rxjs做任何事情之前,这非常重要。
如果要订阅相同的值序列,即如果您希望生产者将其值多播到所有订阅者(热行为),而不是为每个订阅者重新启动(冷行为),则需要使用变体如上述链接中所解释的multicast
运算符。这意味着在你的情况下
var random$ = Rx.Observable.interval(1000)
.map(() => setFlagToRandomTrueOrFalse())
.filter(x => x)
.share();
回到你关于数据传播顺序的问题,它确实主要是确定性的,这并不意味着总是很简单。在您的简单情况下,第一个订阅确实将首先执行。这是因为在幕后,multicast
- 类似的运营商正在使用主题,它按订阅顺序立即(热源)向所有订户发送他们收到的价值。有关主题的信息,请查看What are the semantics of different RxJS subjects?。
最后,如果你编写纯函数,它可以帮助推理你的溪流。拥有一个诸如flag
之类的闭包变量会让事情变得非常复杂。
我建议你先看看这里,然后再深入研究Rxjs:The introduction to Reactive Programming you've been missing
答案 1 :(得分:1)
您可以使用publish() and connect()
按顺序执行操作
var flag = false;
// Stream that non-deterministically emits `true` when flag is true
var random$ = Rx.Observable.interval(1000)
.map(() => setFlagToRandomTrueOrFalse())
.filter(x => x)
.first().publish();
// How can I declare my "subscribes" so that the console.logs happen in order?
var sub1 = random$.subscribe(() => console.log(1), console.log, resetFlagToFalse);
var sub2 = random$.subscribe(() => console.log(2), console.log, resetFlagToFalse);
random$.connect();
function setFlagToRandomTrueOrFalse() {
flag = flag || !!Math.floor(Math.random() * 2);
return flag;
}
function resetFlagToFalse() { flag = false; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.all.js"></script>