2016-08-19 54 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。

相关问题