web-dev-qa-db-ja.com

AngularJSダイジェストループはどのくらいの頻度で実行されますか?

AngularJSのメリットについて説明するとき、他のJSフレームワークに比べてAngularの主な利点として、双方向のデータバインディングがよく宣伝されています。 Digging deeper )、ドキュメントはこのプロセスを示唆していますイベント駆動型の測定ではなくダーティチェックを介して行われます。最初は、ダイジェストループは定期的にメソッドをバックグラウンドで起動し、各サイクル中にすべての_$watch_ esをチェックすることで機能しているようです。ただし、さらに読むと、ダイジェストループは実際にはrootScope.digest()によってトリガーされているようです。これは_$.apply_によってトリガーされ、次にイベント(!)によってトリガーされます。 _ng-click_を介して呼び出されるonClickイベント.

しかし、これはどのようになりますか? Angular 変更リスナーを使用しない と思ったので、ダイジェストループは実際にどのように動作しますか?Does Angularダイジェストループが内部で自動的に開始されますか、それともイベントによってダイジェストループがトリガーされますか?ダイジェストループが自動的に実行される場合、どれくらいの頻度で実行されますか?


いくつかの明確化のポイント:

  • 変更に手動でバインドするときにダイジェストループがどのように実行されるかについては質問していません。この場合、ダイジェストループを強制したい場合は、$.apply()を呼び出して強制できます。
  • また、ユーザーイベントに応答してダイジェストループが実行される頻度についても質問していません。たとえば、ng-modelが入力ボックスにある場合、Angularは、ユーザーが入力を開始するとダイジェストループを開始します。混乱する部分は、ユーザーが入力していたことを知るために、 AngularイベントベースonKeyUpをどこかで使用していませんか?
  • ダイジェストループごとに最大10サイクルの制限があることはすでに知っています。私の質問は、ダイジェストループごとのサイクル数ではなく、たとえば1秒あたりに実行されるダイジェストループの数についてです。
  • おまけの質問:ダイジェストループはJavaScriptイベントループとどのように関連していますか? JSイベントループはバックグラウンドで定期的に実行されますか?ダイジェストループはイベントループと同じですが、「角度のコンテキスト」でのみですか?これらはまったく異なるアイデアですか?
33
derekchen14

角度ダイジェストがトリガーされます-ポーリングでは発生しません。

コードが実行された後、コードが実行され、angularがダイジェストをトリガーします。

例:

 element.on('click', function() {
     $scope.$apply(function() { 
         // do some code here, after this, $digest cycle will be triggered
     });
 });

Angularは、コンパイル/リンクフェーズの後に$ digestもトリガーします。

Compile > Link > Digest

そして、どのくらいのダイジェストサイクルがトリガーされますか?スコープ変数がどれだけ早く安定するかによります。通常、それを決定するには少なくとも2サイクルかかります。

13
pixelbits

主な質問への短い直接的な答えは「いいえ」です、angularは自動的にダイジェストループをトリガーしません。

TL; DR回答:

ダイジェストループは、Angularスコープインスタンスに関連付けられたPOJOモデルに対してダーティーチェックを実行するように設計されているため、モデルが変更される可能性がある場合にのみ実行する必要があります。ブラウザ内で実行される単一ページWebアプリケーションでは、以下のアクション/イベントは、モデルの変更につながる可能性があります

  1. DOMイベント
  2. コールバックを起動するXHR応答
  3. ブラウザの場所の変更
  4. コールバックを起動するタイマー(setTimout、setInterval)

同様に、Angularトリガーダイジェストループなど

  1. 入力ディレクティブ+ ngModel、ngClick、ngMouseOverなど.
  2. $ httpおよび$ resource
  3. $ location
  4. $ timeout

私の理解からこれらのボーナスの質問に答えてみてください:

  1. angular入力ディレクティブ(テキスト、選択など)と一緒に使用されることが多いngModelディレクティブ。後者は "change"イベントをリッスンし、ng値を同期するためにngModelControllerから公開された$ setViewValue APIを呼び出します。 。同期プロセス中に、ngModelControllerは必ずダイジェストループをトリガーします。
  2. ダイジェストループはJSイベントループとは異なり、後者はJSランタイムの概念です(優れた視覚化セッション https://www.youtube.com/watch?v=8aGhZQkoFbQ をチェックアウトして、イベントキューに対して実行します)。消費されたイベントをキューから自動的に削除しますが、明示的に監視しない限り、ダイジェストループは監視リストから監視を削除しません。
  3. 1秒あたりのダイジェストループの数は、ループを通じて実行されるすべてのウォッチコールバックの効率に依存します。不正なコードの終了に1秒かかる場合、このダイジェストループのコストは1秒以上になります。

したがって、angularパフォーマンスの落とし穴を回避するためのいくつかの重要なプラクティス

  1. ウォッチコールバックは、可能な限りシンプル/効率的にコーディングする必要があります。たとえば、複雑なアルゴリズムコードをワーカースレッドなどに切り離します。
  2. 使用されなくなった時計を事前に削除する
  3. 必要に応じて、$ scope。$ apply()ではなく$ scope。$ digest()を呼び出すことをお勧めします。$ digest()はスコープツリーの一部のみを実行し、サブツリーの下に関連付けられたモデルがビューに反映されていることを確認します。しかし、$ apply()はスコープツリー全体に対して実行され、より多くの監視を反復します。
12
Roger Jin

私はこれが起こると信じています。 AngularJSは、モデルの変更はユーザーインタラクションでのみ発生するというスマートな仮定を行いました。これらの相互作用は、

  • マウスアクティビティ(移動、クリックなど)
  • キーボードアクティビティ(キーアップ、キーダウンなど)

対応するイベントのAngularJSディレクティブは、式の実行を$ scope。$ applyにラップします。これは、彼の例の@pixelbitsで示されています。これにより、ダイジェストサイクルが発生します。

AngularJSがダイジェストループをトリガーする他のイベントもあります。 $ timeoutサービスと$ intervalサービスは、そのような2つの例です。これらのサービスにラップされたコードも、ダイジェストループの実行につながります。ダイジェストサイクルの実行を引き起こす可能性がある他のいくつかのイベント\サービスがあるかもしれませんが、これらは主要なものです。

これが、Angularコンテキスト外でモデルを変更しても、ウォッチとバインディングが更新されない理由です。そのため、$ scope。$ applyを明示的に呼び出す必要があります。 jQueryプラグイン。

4
Chandermani