我有以下内容(在咖啡脚本中(
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.应用和肚子痛
Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.6.4/$rootScope/inprog?p0=%24digest
这是因为摘要循环在完全完成运行之前调用主题的下一个方法。这使得$digest循环即使在调用 done 后也能运行。我可以通过将设置超时添加到完成来解决此问题...
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();
}));
所以它们是相同的
我注意到,当我第一次调用应用程序时,开始阶段被调用,但从不清除阶段。现在试图弄清楚为什么。
闪电版本:Angular 不会检查每个摘要上的每个值。只有当更改发生在 $apply(( 内部时,它才知道发生了什么变化。大多数情况下,这是隐藏的,因为它发生在使用标准角度指令/控制器的幕后,并且像往常一样绑定数据。完成后$apply将发生摘要。由于这些更改可以触发正在监视的其他内容,因此摘要将在每个周期运行多次。您看到的错误是因为您正在调用$apply在摘要周期已在进行时调用$digest。
如果更改是从外部来源进行的,即来自第三方的回调,则 angular 不知道它。您是正确的,您需要使用$apply,但是您应该向它传递一个可以在适当时间执行的函数。
我不知道咖啡脚本语法,但我认为这个 javascript 示例应该显示修复程序。
importList.onchange = function(){//callback for onchange
$scope.$apply(function(){ //use $apply an pass in function
constructorSubscription.unsubscribe();
done();
doSomething() ;
});
};
特别是,这个
$rootScope.$apply ->
doSomethingElse()
应该是
$rootScope.$apply (->
doSomethingElse())
EDIt 我在这里错了,特定的语法是错误的
这是一个完整的工作示例 plunker
请注意,setInterval 在 angular 之外,因此它模拟了上面的示例。与此示例相比,如果您打开控制台,您可以看到它正确更改=ing值但不使用$apply。