2016-08-19 55 views
2

我有一個服務,計算一個給定的Sudoku(實現不重要)的解決方案,併發布每個RxJS Observable計算迭代。如何爲RxJS Observable的每個排放創建一個新對象?

solve() : Observable<Field[][]> { 
    let observable = Observable.create((o: Observer<Field[][]>)=> { 
     let iterationCount : number = 0; 
     while (!this.sudokuGame.isFinished() && iterationCount < 500) { 
      iterationCount++; 
      this.eliminateOptions(); 

      o.next(this.sudokuGame.boardFields); 
     } 
     if(this.sudokuGame.isFinished()) 
      o.complete(); 
     else 
      o.error("The game could not be finished after 500 iterations."); 
    }); 
    return observable; 
} 

我這樣做,這樣我可以在以後使用Observable.zip()這個觀察到的結合與Observable.interval()觀測顯示這個解決過程經歷與我的Angular2組分人類明顯的延遲迭代。

但是,當我設置由可觀察在我Angular2組分像這樣發出的數據:

Observable.zip(this.sudokuSolverService.solve(),Observable.interval(500),(obs, timer) => {return obs}).subscribe((nextBoardFields: Field[][]) => { 
     this.sudokuGame.boardFields = nextBoardFields; 
    }); 

然後可觀察到的排放被延遲,但更改顯示瞬間不過。我懷疑這是由於我通過引用複製了nextBoardFields引起的,但是我不知道任何方法可以將我的Angular2控制器中的boardFields -Array與boardFields - 中的數組取消關聯,這是我的sudoku解決服務中的一個方法。

有沒有可能做到這一點?

編輯:那我腦海是以某種方式使Field類不可變的(也許Immutable.js的幫助下),這似乎對這個問題有點複雜的唯一的事情。

回答

0

我已經使用Object.assign()獲取一個對象的值副本,並斷開與observable/observer的連接。你的情況會起作用嗎?

Observable.zip(this.sudokuSolverService.solve(),Observable.interval(500),(obs, timer) => {return obs}).subscribe((nextBoardFields: Field[][]) => { 
    Object.assign(this.sudokuGame.boardFields, nextBoardFields); 
}); 
+0

我確實知道不可變也會起作用,但我同意它增加了一層複雜性,這不會很有趣。 – Maarek

+0

你應該給出一個代碼示例。 – Soviut

+0

你是對的,編輯傳入。 – Maarek

1

我想這個問題在這裏與您的solve觀察到的是,它並同步一氣呵成發出自己的價值觀。所以在同一個嘀嗒聲中,您可以調用所有的onNext,也可以調用onComplete。因此,當zip時,它獲得第一個值,等待計時器,但在此期間,您的可觀察值已經在同一個tick上發出了所有值。你可能需要做的是讓你的迭代變量鏈接到定時器,例如:

Observable.interval(500).scan(function(_, iterationCount){ 
    // your logic here 
    return { 
    iterationCount : iterationCount 
    isFinished : // your logic here 
    boardFields : // your logic here 
    } 
}, {}) 
.doWhile(function(x){return x.iteration < 500 && !x.isFinished}) 
.map(function(x){return x.boardFields}) 
0

Maarek的回答讓我朝着正確的方向前進。

關鍵的是,即使我複製了Field[][] - 陣列與方法,如[].concat(nextBoardFields)或Maarek的Object.assign(this.sudokuGame.boardFields, nextBoardFields),個人Field的仍然指向同一個對象。

要深入複製這個數組,我使用了o.next(JSON.parse(JSON.stringify(this.sudokuGame.boardFields))),它允許我按照預期使用我的Observable。

相關問題