2017-11-11 118 views
1

RxJS 5.5.2爲每個訂閱創建於掃描操作符的新種子對象

我有下面的代碼誰分裂的數字陣列爲對象,具有2個屬性「小」的數字越小則4和'大'其餘。

const o = from([1, 2, 3, 4, 5, 6]).pipe(
    scan<number, {}>((a, b) => { 
    if (b < 4) { 
     a['small'].push(b); 
    } else { 
     a['big'].push(b); 
    } 
    return a; 
    }, { 
    'small': [], 
    'big': [] 
    }) 
); 
console.log('subscription 1'); 
o.subscribe(x => console.log(JSON.stringify(x))); 
console.log('subscription 2'); 
o.subscribe(x => console.log(JSON.stringify(x))); 

認購1控制檯打印後:

{"small":[1,2,3],"big":[4,5,6]} // this is ok 

訂購2臺打印後:

{"small":[1,2,3,1,2,3],"big":[4,5,6,4,5,6]} // this is not ok 

有沒有開始一個新的種子對象每次有人贊同呢?

回答

2

另一種選擇是將管道封裝在defer塊中,該塊將在訂閱時重建源流。

defer(() => 
    from([1, 2, 3, 4, 5, 6]).pipe(
    scan<number, {}>((a, b) => { 
     if (b < 4) { 
     a['small'].push(b); 
     } else { 
     a['big'].push(b); 
     } 
     return a; 
    }, { 
     'small': [], 
     'big': [] 
    }) 
) 
); 

每個訂閱都會調用推遲塊中的方法並訂閱結果。儘管像@arturgrzesiak提到的那樣,變異數組在函數式編程和擴展功能反應式編程中被看作反模式。

2

掃描累加器({ small: [], big: [] })被.push突變,這是一種反模式,可能很容易導致意外的行爲。防止改變先前發出的值

一種選擇可能是:

scan<number, {}>((a, b) => { 
    if (b < 4) { 
    return Object.assign({}, a, {small: a.small.concat([b])}); 
    } else { 
    return Object.assign({}, a, {big: a.big.concat([b])}); 
    } 
}, { 
    'small': [], 
    'big': [] 
}) 

不知道你正在試圖完成什麼,但它可能是值得看一看的partition運營商,這將產生兩個單獨的值流如const [small, big] = someStream.partition(x => x < 4);

+2

看來OP正在使用Typescript,所以你可以簡化使用ES7賦值符號'{... a,small:[... a.small,b]}' – paulpdaniels

+0

@paulpdaniels好點 –