Angular.jsでAJAX呼び出しを行うためのベストプラクティスは何ですか?


151

私はこの記事を読んでいました:http : //eviltrout.com/2013/06/15/ember-vs-angular.html

そしてそれは言った、

規約が欠けているため、コントローラー内で直接AJAX呼び出しなどの悪い習慣に依存しているAngularプロジェクトはいくつあるのでしょうか。依存関係の注入により、開発者はルーターパラメータをディレクティブに注入していますか?初心者のAngularJS開発者は、経験豊富なAngularJS開発者が慣用的であると信じる方法でコードを構成しようとしていますか?

実際$httpにAngular.jsコントローラーから呼び出しを行っています。なぜそれが悪い習慣なのですか?では、$http電話をかけるためのベストプラクティスは何ですか?なぜ?


12
+1は、emberとangularjsを比較する興味深い投稿を参照します。
Chandermani 2013

私は約同じことを疑問に思ってアンギュラベストプラクティス
Dalorzo

また、補足として、APIをチェックして、見逃していないかどうかを確認してください:docs.angularjs.org/api/ng/service/$http
Christophe Roussy

回答:


174

編集:この回答は主にバージョン1.0.Xに焦点を当てていました。混乱を避けるために、2013-12-05現在のAngularの現在のすべてのバージョンに対する最良の回答を反映するように変更されています。

アイデアは、返されたデータにプロミスを返すサービスを作成し、それをコントローラーで呼び出し、そこでプロミスを処理して$ scopeプロパティを設定することです。

サービス

module.factory('myService', function($http) {
   return {
        getFoos: function() {
             //return the promise directly.
             return $http.get('/foos')
                       .then(function(result) {
                            //resolve the promise as the data
                            return result.data;
                        });
        }
   }
});

コントローラー:

promiseのthen()メソッドを処理してデータを取得します。$ scopeプロパティを設定し、必要に応じて他のことを行います。

module.controller('MyCtrl', function($scope, myService) {
    myService.getFoos().then(function(foos) {
        $scope.foos = foos;
    });
});

インビュープロミス解決(1.0.Xのみ):

ここでの元の回答のターゲットであるAngular 1.0.Xでは、ビューによって特別な扱いが約束されます。それらが解決されると、解決された値がビューにバインドされます。これは1.2.Xで廃止されました

module.controller('MyCtrl', function($scope, myService) {
    // now you can just call it and stick it in a $scope property.
    // it will update the view when it resolves.
    $scope.foos = myService.getFoos();
});

4
言うまでもなく、これ$scope.foosはテンプレートでプロパティを使用する場合にのみ機能します。テンプレートの外で(たとえば、別の関数で)同じプロパティを使用する場合、そこに格納されているオブジェクトは、promiseオブジェクトのままです。
クラークパン

1
私は現在、このパターンを新しいAngularアプリで使用していますが、この例では、getFoosからデータを取得して変更をポストしたい場合に、スコープにバインドしたプロパティにアクセスする方法を不思議なページで疑問に思っていますそれ。アップデートで$ scope.foosにアクセスしてアクセスすると、データではなくpromiseオブジェクトがあり、オブジェクト自体でデータを取得する方法を確認できますが、本当にhacky.ideasのように見えますか?
ケリーミリガン2013

5
@KellyMilligan、このパターンでは、Promiseの処理方法を知っているのはバインディングです。他の場所からオブジェクトにアクセスする必要がある場合.then()は、promiseのを処理して、値を$ scope ...に入れる必要があります...myService.getFoos().then(function(value) { $scope.foos = value; });
Ben Lesh

1
1.2.0-rc.3の時点で、この手法の更新のみで、promiseの自動アンラップは廃止されたため、この手法は機能しなくなります。
クラークパン

2
おそらく最近のバージョンのAngularと一致しなくなったためと思われます。それを反映するように答えを更新しました。
Ben Lesh

45

ベストプラクティスは、$http呼び出しをコントローラーにデータを提供する「サービス」に抽象化することです。

module.factory('WidgetData', function($http){
    return {
        get : function(params){
            return $http.get('url/to/widget/data', {
                params : params
            });
        }
    }
});

module.controller('WidgetController', function(WidgetData){
    WidgetData.get({
        id : '0'
    }).then(function(response){
        //Do what you will with the data.
    })
});

$httpこのように呼び出しを抽象化すると、このコードを複数のコントローラーで再利用できます。これは、このデータと対話するコードがより複雑になったときに必要になります。おそらく、コントローラーで使用する前にデータを処理し、そのプロセスの結果をキャッシュして、再処理に時間を費やす必要がないようにしたい場合があります。

「サービス」は、アプリケーションが使用できるデータの表現(またはモデル)と考える必要があります。


9

受け入れられた答えは私に$http is not definedエラーを与えていたので、私はこれをしなければなりませんでした:

var policyService = angular.module("PolicyService", []);
policyService.service('PolicyService', ['$http', function ($http) {
    return {
        foo: "bar",
        bar: function (params) {
            return $http.get('../Home/Policy_Read', {
                params: params
            });
        }
    };
}]);

主な違いはこの行です:

policyService.service('PolicyService', ['$http', function ($http) {

1

Angularで完全に汎用的なWebサービスを求めていた人に答えを示しました。プラグインするだけをお勧めします。自分でコーディングする必要なく、すべてのWebサービス呼び出しを処理します。答えはここにあります:

https://stackoverflow.com/a/38958644/5349719

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.