我有一个服务来计算给定数独(实现不重要)的解决方案,并在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与Observable.interval()
观察者结合起来,以显示此解决过程经历的迭代,并且人类在我的Angular2组件中会有明显的延迟
但是,当我在Angular2组件中设置Observable发出的数据时,如下所示:
Observable.zip(this.sudokuSolverService.solve(),Observable.interval(500),(obs, timer) => {return obs}).subscribe((nextBoardFields: Field[][]) => {
this.sudokuGame.boardFields = nextBoardFields;
});
然后Observable的排放被推迟,但是变化立即显现出来。我怀疑这是由于我通过引用复制nextBoardFields
- 数组引起的,但是我不知道有任何方法要取消boardFields
- 我的Angular2控制器中的数组与boardFields
- 数组的链接在我的数独解决服务中。
有可能这样做吗?
编辑:我唯一想到的就是以某种方式使Field
类不可变(也许在Immutable.js的帮助下),这似乎有点复杂物质
答案 0 :(得分:1)
我猜你的solve
可观察对象的问题是它同步并一次性发出它的值。因此,在同一个刻度中,您调用了所有onNext
,以及onComplete
。因此当你zip
时,它获得第一个值,等待计时器,但同时,你的observable在同一个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})
答案 1 :(得分:0)
我使用Object.assign()获取对象的by值副本并断开与observable / observer的连接。这会对你的情况有用吗?
Observable.zip(this.sudokuSolverService.solve(),Observable.interval(500),(obs, timer) => {return obs}).subscribe((nextBoardFields: Field[][]) => {
Object.assign(this.sudokuGame.boardFields, nextBoardFields);
});
答案 2 :(得分:0)
Maarek的回答让我朝着正确的方向前进。
关键是,即使我使用Field[][]
或Maarek&#39; [].concat(nextBoardFields)
等方法复制Object.assign(this.sudokuGame.boardFields, nextBoardFields)
- 数组,个人Field
&#39 ; s仍然会引用相同的对象。
为了深度复制这个数组,我使用了o.next(JSON.parse(JSON.stringify(this.sudokuGame.boardFields)))
,它允许我按预期使用我的Observable。