30

最近、何人かの同僚と私は、AngularJS サービスが状態を持つべきかどうかについて話し合っていました。私たちはそれに対する賛否両論をいくつか出しましたが、私はこの件について追加の考えやフィードバックを得たいと思っていました. 私の検索でこれを見つけましが、言及されている明確なベストプラクティスはないようです。クライアント側のない世界では、サービスは決して状態を保持すべきではありませんが、別の問題であるため、クライアント側で許容できるのではないかと考え始めています。

サービスが状態を保持する理由:

  1. 複数のスレッドからサービスにアクセスすることはありません。各ブラウザには、サービスの独自のインスタンスがあります。
  2. rootScope に保存するのではなく、サービスが関心のある状態のみを保持できるようにします。カプセル化します

サービスが状態を保持しない理由:

  1. サービスは冪等ではなくなりました。呼び出し関数は状態を変更する可能性があるため、サービスの状態に基づいて呼び出したときに異なる結果になる可能性があります。
  2. 全体として、これはテストしやすいと思います。

「状態を保持するサービス用」セクションの #2 に対処する 1 つの方法は、アプリケーションの現在の状態を含む rootScope に appState オブジェクトを設定することです。次に、すべての状態が 1 つの場所に集められ、サービスで必要なものをそこから引き出すだけです。これを見つけて疑問に思った

4

4 に答える 4

17

おそらく「状態」の意味にもよるでしょうが、多くの場合、答えはイエスだと思います。サービスは状態を保持する必要があります。

たとえば、API との通信を担当するサービスがある場合、そのサービスは認証状態を保持できます。

ところで、AngularJS サービスにとって冪等性がどの程度重要かはわかりません。それらはシングルトンであるため、本質的に何らかの状態を持っています。サービスでべき等メソッドを作成することもできます (場合によっては作成する必要があります) が、それは別の問題です。

于 2013-01-09T16:44:45.853 に答える
11

AngularJS では、サービスは factory function 経由で渡されます。基本的に、それらは何らかの状態を含むことができるオブジェクトです (たとえば、アクションを実行するために必要なデータをキャッシュまたは保存するため)。

状態を持つ/持たないという両方の短所を取ることができる1つの良い解決策は、状態を含むオブジェクトを返すサービス(実際には関数である可能性があります)です。

サービスを見てみましょう$http: このサービス呼び出しのインスタンスを取得できます

var x = $http({url:'...'});

そして、電話する

var result = x.get() //actually `$http.get` is shortcut of this operation

と同じngResource: service を使用して、目的のアクションを実行できる状態のオブジェクトを取得します。

したがって、基本的にはそれが最良の選択肢だと思います。ある時点から、アクションによって変更される可能性のある状態をサービス自体に保存するのではなく、別のオブジェクトに移動することで「副作用」を回避しますが、そのオブジェクトに特定の状態を持たせることができますカスタム情報 (認証情報など) を保存します。

于 2013-01-09T18:02:42.253 に答える
2

IMO はい、サービスは状態を持つことができます。サービスとして「できる」と言うのは、従来のクライアント サービスではないサービス (プロバイダー) に似たものと考えることができますが、angularJS ではまったく異なるものを意味する場合もあります。アプリの rootScope-y one-instance 要素として、たとえば、状態を管理するためだけに使用できます。私の場合、これにより、状態構造が多くのアプリで同じであることを確認できます。個々の状態構造体がブートストラップ内でそれぞれに定義されていても、モジュールが変更されると、セッション状態などは常に同じで更新されます。

于 2013-01-09T17:42:13.043 に答える
-5

サービスに状態を持たせない理由は、複数のスレッドがサービスにアクセスしている場合に競合状態が発生するためです。

サービスの状態に関する一般的な問題は次のとおりです。

  1. スレッド 1 が状態に書き込みます
  2. スレッド 2 が状態に書き込みます
  3. スレッド 1 は状態から読み取ります
  4. スレッド 2 は状態から読み取ります

スレッド 1 の値が間違っています。

そうは言っても、javascript は現在シングル スレッドであるため、このようなスレッド アクセスの問題は発生しません。ただし、複数の非同期 $http 呼び出しがすべて同じサービス変数に書き込んでいるサービスがあった場合は心配です。夜ぐっすり眠れるようにするためだけに、すべてのサービス メソッドを記述して、実際のデータのパススルーになるようにします。

代わりに、サービスで状態を維持するのではなく、可能な限りバックエンドに状態を配置することを検討できます。「認証済み」または幅と高さのようなものを維持し、照会することができます。これにより、ユーザーがアプリから離れて移動し、戻ってきて、すべての設定がまだセットアップされ、ログインされていることを確認できる可能性が開かれます。セッション ID を Cookie に保存し、これらすべてをバックエンドに保存できます。

状態を保存する別のオブジェクトを持つルートに行った場合、状態の何かが変更されたときにサービスから $emit できる可能性があります: how to emit events from a factory . これには、複数のサービスが統一されたアプリケーションの状態を変更できるという良い副作用があります。これは、状態が 1 つのサービスに格納されていない (または複数のサービスに分散している) ためです。

于 2014-01-07T04:42:58.767 に答える