ディレクティブテストにおける$ applyと$ digest


98

スコープの特定の属性のステータスに応答するディレクティブがあり、テストでその属性を変更して正しく応答することを確認したい場合、その変更を行うための最良の方法はどれですか。

私はこれらの両方のパターンを見てきました:

scope.$apply(function() {
    scope.myAttribute = true;
});

そして

scope.myAttribute = true;
scope.$digest();

それらの違いは何ですか?どちらが優れていますか?

回答:


206

scope.$digest()現在のスコープとそのすべての子に対してウォッチャーを起動します。scope.$apply渡された関数を評価して実行し$rootScope.$digest()ます。

1つ目は、現在のスコープとその子のウォッチャーを評価する必要があるため、より高速です。2つ目はウォッチャーと$rootScopeそのすべての子スコープを評価する必要があるため、速度が遅くなります。

ウォッチャーの1つでエラーが発生し、を使用すると、エラーはサービスscope.$digest経由では処理されない$exceptionHandlerため、例外を自分で処理する必要があります。内部でブロックをscope.$apply使用し、try-catchすべての例外をに渡します$exceptionHandler


1
ウィル$digestもスコープの子で呼び出すこと?
ピラウ

15
これは誤解を招く可能性があります。$digest現在のスコープだけでなく、そのすべての子に対してもウォッチャーを起動します。
tasseKATT 2014年

@tasseKATT、私はあなたのコメントが示唆しているものをキャプチャしたと思います。
activedecay 2016

12

ドキュメント自体が言及しているように、$ digestサイクルはいつでも実行されます$scope.$applyスコープに関する開発者ガイドに従って

式を評価した後、$ applyメソッドは$ digestを実行します。$ digestフェーズでは、スコープはすべての$ watch式を調べ、以前の値と比較します。

そして、スコープAPI ドキュメントに従って

通常、コントローラーやディレクティブで$ digest()を直接呼び出すことはありません。代わりに(通常はディレクティブ内から)$ apply()を呼び出すと、$ digest()が強制されます。

したがって$digest、明示的にを呼び出さないでください$apply。メソッドを呼び出すと、ダイジェストサイクルがトリガーされます。


8
現在のスコープとその子だけを評価する必要があるほとんどの場合、ダイジェストで十分なので、これは当てはまりません。$ scope。$ applyが内部的に$ digestを呼び出すことは事実ですが、$ rootScope。$ digest()を呼び出すことになるため、非常に重いことを覚えておくことは非常に重要です
Srivathsa Harish Venkataramana
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.