2017-08-04 32 views
0

我有以下的(在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的在完全運行之前的下一個方法。即使完成調用,這也會使$ 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叫,但從來沒有明確的階段。試圖弄清楚爲什麼現在。

回答

-1

閃電版本: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()) 

編輯我錯了這裏與特定的語法,這是錯誤

Here's a full working example plunker

注意的setInterval是外的角度,所以它模擬你上面的例子。與This Example相比,如果你打開你的控制檯,你可以看到它正確地改變了值,但沒有使用$ apply。

+0

我無法更改onchange的聲明,因爲它在我的代碼中,並且代碼不應該處理應用程序,所以如果需要,應該讓Angular處理它。我只需要在測試中混淆適用。所以我需要在我打電話申請之前申報我的訂閱,那麼我會如何包裝呢? – Jackie

+0

是啊,我不認爲這會工作,因爲我不能包裝我的聲明在申請,這是我認爲這將需要。 – Jackie

+0

對不起,但我想我將不得不投票回答這個問題,因爲我知道所有這一切,並沒有解決任何問題,我會等一會兒,直到你回覆 – Jackie

相關問題