25

angularJS イベント処理のコンテキストで、2 つのことを考えていました。

  1. 同じイベントをリッスンするハンドラーがトリガーされる順序はどのように定義されますか?
  2. これについて疑問に思い始めたら、それは悪い設計の兆候ですか?

angular $on、$broadcast、$emit、およびネイティブDOM イベント フローに関するドキュメントを読んだ後、さまざまなスコープでイベント ハンドラーがトリガーされる順序を理解したと思います。問題は、複数のハンドラーがさまざまな場所 (コントローラーとサービスなど) から同じスコープ (たとえば $rootScope) でリッスンする場合です。

問題を説明するために、1 つのコントローラーと 2 つのサービスを備えた jsfiddle をまとめました。すべて $rootScope http://jsfiddle.net/Z84tX/を介して通信します。

Thanks

4

6 に答える 6

26

とても良い質問です。

イベントハンドラは初期化順に実行されます。

私のハンドラーはどちらが最初に実行されるかを知る必要がなかったため、これについてはこれまであまり考えたことがありませんでしたが、フィドルを見ると、ハンドラーが初期化されたのと同じ順序で呼び出されていることがわかります。

あなたのフィドルにはcontrollerA、2つのサービスに依存するコントローラーがServiceAありServiceBます。

myModule
  .controller('ControllerA', 
    [
      '$scope', 
      '$rootScope', 
      'ServiceA', 
      'ServiceB', 
      function($scope, $rootScope, ServiceA, ServiceB) {...}
    ]
  );

サービスとコントローラーの両方がイベント リスナーを定義します。

ここで、注入する前にすべての依存関係を解決する必要があります。つまり、両方のサービスがコントローラーに注入される前に初期化されます。したがって、サービス ファクトリはコントローラーの前に初期化されるため、サービスで定義されたハンドラーが最初に呼び出されます。

次に、サービスが注入された順序で初期化されることも確認できます。Soは、その順序でコントローラーに注入されるため、ServiceA前に初期化されます。ServiceBコントローラー署名内で順序を変更した場合、初期化順序も変更されていることがわかります ( のServiceB前に来ますServiceA)。

そのため、サービスが初期化された後、コントローラーも初期化され、それとともに、内部で定義されたイベント ハンドラーも初期化されます。

したがって、最終結果は、$broadcast では、ハンドラーは次の順序で実行されます:ServiceAハンドラー、ServiceBハンドラー、ControllerAハンドラー。

于 2013-07-03T15:29:12.550 に答える
3

このルートを使用するのは少し面倒ですが (お勧めしません)、serviceB が serviceA の前に初期化されることを保証できず、serviceB のリスナーを最初に実行する必要がある場合に備えて、代替手段を提供したいと考えました。

配列を操作して、$rootScope.$$listenersserviceB のリスナーを最初に配置できます。

$rootScopeserviceBにリスナーを追加すると、次のように機能します。

var listener, listenersArray;
$rootScope.$on('$stateChangeStart', someFunction);
listenersArray = $rootScope.$$listeners.$stateChangeStart;
listener = listenersArray[listenersArray.length - 1];
listenersArray.splice(listenersArray.length - 1, 1);
listenersArray.unshift(listener);
于 2015-08-07T21:31:49.013 に答える
1

私は Angular JS の初心者なので、答えが最適でない場合はご容赦ください。:P

イベントによってトリガーされる関数の順序が依存する必要がある場合 (つまり、関数 A の次に関数 B)、トリガー関数を作成しない方がよいでしょうか?

function trigger(event,data) {
    FunctionA(event,data);
    FunctionB(event,data);
}

$rootScope.on('eventTrigger',trigger);
于 2013-08-22T04:12:16.243 に答える