現在のスコープをAngularJSサービスに渡す


106

「現在の」$scopeをAngularJSサービスに渡すことは正しいですか?

$ serviceが1つのコントローラーでのみ使用されていることを知っている状況で、$ serviceメソッド自体にコントローラーのスコープへの参照が必要です。

これは哲学的に正しいですか?

または、イベントを$ rootScopeにブロードキャストしてから、コントローラーがそれらをリッスンするほうがよいですか?


1
何をしようとしているのか具体的に教えていただけますか?おそらく、サービスにスコープをプッシュする必要はまったくありませんか?
ガナラジ2013年

まあ、それほど難しくはありません。簡単に言うと、$scopeプロパティにアクセスして、$scope.$apply必要なときに呼び出すことができるようにしたいのです。
SC

さらに、$ serviceからの変更を$ scopeに適用したいとします。それが今よりはっきりしていることを願っています。
SC

8
サービスにアクセスさせたい$ scopeプロパティを(コントローラーに置くのではなく)サービス自体に置くことをお勧めします。サービスは、コントローラーよりもモデル/データを格納するのに適しています。
Mark Rajcok 2013年

@MarkRajcock私もこの問題を理解しようとしています。現在、サービスを呼び出して、提供されたデータをコントローラーにアタッチしてい$scopeます。コントローラーは、サービス内のデータに直接アクセスし、これを行わずにビューに渡すにはどうすればよいですか?
drjimmie1976 14

回答:


67

非同期が発生したときにコントローラーに通知するには、Angular promiseを使用します

$apply呼び出すには$rootScope.$apply、スコープは必要ありません。特定のスコープでもルートでも呼び出すことができるため、を呼び出すことができます。

変数の読み取りに関しては、パラメーターを受け取った方がよいでしょう。しかし、スコープからオブジェクトパラメーターとして読み取ることもできますが、パラメーターを使用すると、サービスインターフェイスがより明確になります。


これが私のAngularJS初心者の疑問をよりよく解決する答えだと思います。
SC

@Caio Cunhaスコープを渡すのが良くない理由を詳しく教えてください。私はまさにこの問題を抱え$scopeています、非同期executeSql()関数を使用してサービスへの呼び出しを介していくつかのものを追加したいと思います。3つのオプションを検討します(1)非同期関数でコールバックを使用してから$scope.$apply...これは機能しますが、醜いです(2)$scope非同期関数に渡してからtheScope.$apply()...これも機能します(3)プロミスを使用します。 ..これはまだ試していません。なぜ約束は最善の方法ですか?ありがとう!
drjimmie1976 2014

15

あなたの機能がサービスを必要としないよりも1つのコントローラーにのみ固有である場合、私は言うでしょう。

コントローラのタスクは特定のモデルを操作することですが、サービスはグローバルタスクを処理する必要があります。私は物事を混同する代わりに、このパラダイムに固執したいと思います。

これはドキュメントが言うことです

サービス

Angularサービスは、Webアプリに共通の特定のタスクを実行するシングルトンです

コントローラ

Angularでは、コントローラーはJavaScript関数(タイプ/クラス)であり、ルートスコープを除く、Angle Scopeのインスタンスを拡張するために使用されます。

PS:それ以外に、ダイジェストする必要がある場合は、サービス内に$ rootScopeを挿入することもできます。


2
ありがとう。素晴らしい返事。私の状況に深く入ると、ポイントはシングルトンが欲しいのでServiceを使用しているということです。サービスを使用するコントローラーは1つしかありませんが、このコントローラーはアプリのライフサイクル中に何度もインスタンス化される可能性があるため、サービスを常に同じ状態にしておく必要があります。
SC

とにかく、$ rootScopeの呼び出し$applyまたは呼び出しについての説明は$digest、私には完全に理にかなっています。
SC

1
それでも、テストのためにサービスに分割しておくつもりです。
bluehallu 2014

機能がコントローラーの1つのインスタンスに固有である場合は、サービスの実装をスキップできますが、それ以外の場合は、それらのインスタンス間で状態を共有する機能を犠牲にするので、できません。さらに、今日は単一のタイプのコントローラーがあるからといって、明日機能を活用できる別のコントローラーが存在しないという意味ではありません。さらに、サービスはコントローラーの肥大化を回避できます。つまり、単一のコントローラーがあるかどうかということではなく、どのような機能が問題であるかということです。
Nick

9

はい。初期化するときに$ scopeをサービスに渡すことができます。サービスコンストラクターでは、スコープをthis._scopeのようなものに割り当て、サービス内でスコープを参照できます。

angular.module('blah').controller('BlahCtrl', function($scope, BlahService) {

    $scope.someVar = 4;

    $scope.blahService = new blahService($scope);

});

angular.module('blah').factory('blahService', function() {

    //constructor
    function blahService(scope) {
        this._scope = scope;

        this._someFunction()
    }

    //wherever you'd reference the scope
    blahService.prototype._someFunction = function() {

        this._scope['someVar'] = 5;

    }

    return blahService;

});

1
ただし、+ 1、ただし、$scope特定のコントローラーがサービスを注入するたびに、各コントローラーの値を自動的に知る方法を知りたい$scopeです。これにより、サービスのメソッドを呼び出して手動で渡す必要がなくなります。
Cody

2
@Cody依存性注入と矛盾するため、お勧めしません
Coldstar

同意して、私を撃墜するための+1!おそらく肉屋もDIPする-冗長になるリスクがある。
コーディ

ここでは、サービスを工場と混合しています。このソリューションでは、サービスとは異なるファクトリを使用します。主な違いは、サービスが(シングルトン)オブジェクトを返すことです。一方、ファクトリはインスタンス化できる関数を返します(new MyFunction())。質問は、通話newがオプションではないサービスに関するものでした。
Karvapallo 2015

@Karvapallo良い点。対抗点として、角度のあるサービスは工場、サービス、プロバイダー(ng-wat)を指していると思いますか?
user12121234 2015

6

個人的には$scope、サービスへの受け渡しは悪い考えだと思います。これは、一種の循環参照を作成するためです。コントローラーはサービスに依存し、サービスはコントローラーのスコープに依存します。

関係の点で混乱している上に、このようなことはガベージコレクターの邪魔になってしまいます。

私が好むアプローチは、ドメインオブジェクトをコントローラースコープに入れ、それをサービスに渡すことです。このように、サービスは、コントローラー内で使用されるか、将来的に別のサービス内で使用されるかに関係なく機能します。

たとえば、サービスが配列から要素をプッシュおよびポップすることになっている場合errors、私のコードは次のようになります。

var errors = [];
$scope.errors = errors;
$scope.myService = new MyService(errors);

次に、サービスはで操作することにより、コントローラーと対話しerrorsます。もちろん、配列参照全体を消去しないように注意する必要がありますが、結局のところ、これは一般的なJSの懸念事項です。

私は放送$applyや同様のものを使いたくありません。なぜなら、私見の良いOOの実践は常にどんなAngular-magicよりも優先されるからです。


1
このコードはこれと何か違いがありますか?:$scope.errors = []; $scope.myService = new MyService($scope.errors);
Soldeplata Saketos '21

@SoldeplataSaketos-はい、そうです。errorsから独立して生活してい$scopeます。それがこの回答の要点です。Plsはテキストで提供したリンクを確認します。乾杯。
Marco Faustinelli 2017

1
私があなたのコードを正しく理解している場合、$scope.errorsはを指してvar errorsおり、変数エラーは単なるポインタなので、私には冗長に見えます。私が考えることができる同様の状況の1つであり、それが露骨に冗長であることは、次のコード部分ですconst errors = errors2 = errors3 = []; $scope.errors = errors;。あなたが提供したコードの一部だけでvar errors = []は冗長であると思われることに同意しますか?
Soldeplata Saketos 2017

いいえ、ちがいます。私は言葉によって自分自身の言葉を繰り返し:errors独立の生活します$scope。ドメインオブジェクトとは何か、var割り当てとは何かを理解する必要があります。私が提供したリンクが十分でない場合、利用可能な他の資料がたくさんあります。
Marco Faustinelli 2017

まあ、それは関数の実装にのみ依存しますMyService(errors)。私の理解では、サービスはパラメーター(この場合はポインター)に基づいてロギング配列を生成する必要があります。サービスは角張ったシングルトンなので、私にはそれは悪いパターンです。サービスの実装が適切にプログラムされている場合は、内部変数で配列を生成する必要があります(シングルトンであり続けるため)。したがって、サービスの外部で変数を初期化しても意味がありません。
Soldeplata Saketos 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.