我有以下(在Coffeescript中)
beforeEach "We should see the list changed event", (done) ->
constructorSubscription = importList.onListChanged().subscribe ->
# Expects
constructorSubscription.unsubscribe()
done()
doSomething()
$rootScope.$apply()
it "Actual Test", (done) ->
importList.onListChanged().subscribe ->
# Expect conditions
done()
doSomethingElse()
$rootScope.$apply()
当这个测试运行时,它会进入$ rootScope.apply和腹部疼痛
Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.6.4/$rootScope/inprog?p0=%24digest
这是因为摘要循环在完全运行之前调用了Subject的下一个方法。即使在调用done之后,这也会使$ digest循环继续运行。我可以通过添加setTimeout来完成这个...
setTimeout -> done()
只要摘要花费的时间不超过它的超时时间,但这真的很麻烦。
是否有一个事件可以关闭,告诉我摘要何时完成?
其他信息
其他信息
正在测试的代码是一个RXJS主题,所以doSomething正在调用这样的东西......
@subject = new window.Rx.Subject()
...
onListChanged: =>
@subject.filter (message)=> # filter logic
...
doSomething: =>
@subject.next someValue
doSomethingElse: =>
@subject.next otherValue
如果我删除了$ apply,那么我会收到超时错误
我也尝试了这个,但它不起作用
$timeout -> $rootScope.$apply()
$timeout.flush()
但它没有帮助
更新
我按照答案尝试了这个,但它并没有让我任何地方
beforeEach "We should see the list changed event", (done) ->
constructorSubscription = importList.onListChanged().subscribe ->
# Expects
constructorSubscription.unsubscribe()
done()
$rootScope.$apply ->
doSomething()
it "Actual Test", (done) ->
importList.onListChanged().subscribe ->
# Expect conditions
done()
$rootScope.$apply ->
doSomethingElse()
但它仍然表示摘要周期正在运行
我也试过
beforeEach "We should see the list changed event", (done) ->
doSomething()
$rootScope.$apply ->
constructorSubscription = importList.onListChanged().subscribe ->
# Expects
constructorSubscription.unsubscribe()
done()
it "Actual Test", (done) ->
doSomethingElse()
$rootScope.$apply ->
importList.onListChanged().subscribe ->
# Expect conditions
done()
这也不起作用,并且使用相同的摘要进行错误
失败接下来我尝试了这个......
$rootScope.$apply -> done();
我再次看到相同的结果。
对于那些没有广泛使用过CS的人
$rootScope.$apply ->
doSomethingElse()
编译到
$rootScope.$apply(function() {
return doSomethingElse();
});
,而
$rootScope.$apply (->
doSomethingElse())
编译到
$rootScope.$apply((function() {
return doSomethingElse();
}));
所以它们是相同的
我注意到,当我第一次打电话时,会调用beginPhase但从不清除阶段。试着找出原因。
答案 0 :(得分:-1)
Lightning版本:Angular不会检查每个摘要上的每个值。它只知道如果更改发生在$ apply()内部会发生什么变化。大多数情况下,当使用标准角度指令/控制器并且像往常一样绑定数据时,它会隐藏在幕后。完成$ apply后,就会发生摘要。由于这些更改可以触发正在观看的其他内容,因此摘要将在每个周期运行多次。您看到的错误是因为您正在调用$ apply,当摘要周期正在进行时调用$ digest。
如果从外部来源进行更改,即来自第三方的回调,则角度不知道它。你需要使用$ apply是正确的,但你应该传递一个它可以在适当的时间执行的函数。
我不知道咖啡脚本语法,但我认为这个javascript示例应该显示修复。
importList.onchange = function(){//callback for onchange
$scope.$apply(function(){ //use $apply an pass in function
constructorSubscription.unsubscribe();
done();
doSomething() ;
});
};
编辑:您为实现上述目标所做的coffeescript更改存在错误。
特别是,这个
$rootScope.$apply ->
doSomethingElse()
应该是
$rootScope.$apply (->
doSomethingElse())
EDIt我错了具体的语法错误
Here's a full working example plunker
请注意,setInterval超出了角度,因此它模拟了上面的示例。与This Example相比,如果你打开你的控制台,你可以看到它正确改变了值但不使用$ apply。