簡體   English   中英

RxJS掃描和組合行為

[英]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() ,以便在訂閱者之間共享來自scanObservable

所以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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM