[英]RxJS scan and combinelatest behavior
我一直在學習RxJs,我在嘗試確定使用scan和combinelatest時看到的輸出背后的邏輯時遇到了問題
我有這個示例應用程序
var subject = new Rx.Subject(); var stream = subject.map(function(x) { return function(v) { return v + " stream"; }; }); var state = Rx.Observable.merge(stream) .startWith("StartWith") .scan(function(x, f) { console.log("scan"); return f(x); }); var view1 = state.map(function(x) { return "view1 " + x; }); var view2 = state.map(function(x) { return " view2 " + x; }); Rx.Observable.combineLatest(view1, view2, function(x, y) { return [x, y].join(","); }).subscribe(function(x) { console.log(x); }); subject.onNext("Once"); subject.onNext("Twice");
當您查看應用程序的控制台日志時,它會輸出以下內容
LOG: view1 StartWith, view2 StartWith,
LOG: scan
LOG: view1 StartWith stream, view2 StartWith,
LOG: scan
LOG: view1 StartWith stream, view2 StartWith stream,
LOG: scan
LOG: view1 StartWith stream stream, view2 StartWith stream,
LOG: scan
LOG: view1 StartWith stream stream, view2 StartWith stream stream,
我不明白為什么經常調用掃描。 我只是為主題調用了兩次,但似乎是4次調用掃描功能。 如果我添加更多視圖,它將再添加2個掃描調用,依此類推。
任何人都可以解釋為什么會這樣嗎?
這是因為你訂閱了兩次。 CombineLatest
將隱式訂閱您傳遞它的兩個流。 當您第一次使用Rx時,這是非常常見的錯誤,除非運營商聲稱為每個訂閱共享基礎observable,否則每個訂閱將創建一個新的 Observable流。
也就是說,上面的代碼在功能上與以下代碼相當(但實際上並不這樣做):
var subject = new Rx.Subject();
var source1 = subject
.map(function(x) {
return function(v) {
return v + " stream";
};
})
.startWith("StartWith")
.scan(function(x, f) {
console.log("scan");
return f(x);
}).map(function(x) {
return "view1 " + x;
});
var source2 = subject
.map(function(x) {
return function(v) {
return v + " stream";
};
})
.startWith("StartWith")
.scan(function(x, f) {
console.log("scan");
return f(x);
})
.map(function(x) {
return " view2 " + x;
})
var x, y;
source1.subscribe(function(_x) {
x = _x;
if (typeof y !== 'undefined') {
console.log([x, y].join(","));
});
source2.subscribe(function(_y) {
y = _y;
if (typeof x !== 'undefined') {
console.log([x, y].join(","));
});
subject.onNext("Once");
subject.onNext("Twice");
如果您希望只掃描一次掃描,則應在scan()
之后使用share()
,以便在訂閱者之間共享來自scan
的Observable
。
所以state
應該是:
var state = Rx.Observable.merge(stream)
.startWith("StartWith")
.scan(function(x, f) {
console.log("scan");
return f(x);
})
.share();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.