web-dev-qa-db-ja.com

AngularJSの約束、$ q、延期

[〜#〜]編集[〜#〜]

最初の答えはエレガントですが、この質問とstackoverflowに関する別の質問で何度か述べたように、問題は、データが実際に到着する前にサービスとコントローラーが動作することです。

(最初の回答の最後のコメント:)

はい、問題は、サービスが実行されてすべてがコントローラーに返された後にAPI呼び出しが終了することです。ここでscreencast.com/t/uRKMZ1IgGpb7を参照してください...これは私の基本的な質問です。到着?

それは私が繰り返し言っているようなものですデータの取得が成功した後で配列にデータを入力するサービスを作成し、これがすべて発生した後にコントローラーがデータを取得する方法スクリーンショット、物事は別の順序で実行されます。


私はこのコードを持っています:

 var deferred = $q.defer();
            $http.get('../wordpress/api/core/get_category_posts/?category_id=14 ').success(function(data) {
                //we're emptying the array on every call
                theData = [];
                catName = data.category.slug;
                theData = data;
                theData.name = catName;
                aggregatedData.Push(theData);
            });
            $http.get('../wordpress/api/core/get_category_posts/?category_id=15 ').success(function(data) {
                theData = [];
                catName = data.category.slug;
                theData = data;
                theData.name = catName;
                aggregatedData.Push(theData);
            });
            $http.get('../wordpress/api/core/get_category_posts/?category_id=16 ').success(function(data) {
                theData = [];
                catName = data.category.slug;
                theData = data;
                theData.name = catName;
                aggregatedData.Push(theData);
            });
            $http.get('../wordpress/api/core/get_category_posts/?category_id=17 ').success(function(data) {
                theData = [];
                catName = data.category.slug;
                theData = data;
                theData.name = catName;
                aggregatedData.Push(theData);
            });
            //deferred.resolve(aggregatedData);
            $timeout(function() {
                deferred.resolve(aggregatedData);
            }, 1000);
            /*//deferred.reject('There is a connection problem.');
            if (myservice._initialized) {
                $rootScope.$broadcast('postsList', deferred.promise);
            }*/
            //myservice._initialized = true;
            myservice = deferred.promise;
            return deferred.promise;

私の人生では、結果の配列を遅延させるために渡すときになぜタイムアウトを設定する必要があるのか​​理解できませんか?

原則はそうであるべきではありません、deferは情報が来るのを待ってから約束を返しますか?そこで1秒のポイントは何ですか?私が理解していることから、deferは、APIが結果を返し、約束されたデータを返すのに必要なだけ待つことができるはずです。

私は本当に混乱しています。タイムアウトを設定したときだけ、コントローラーでデータを受信して​​いなかったため、過去2時間、壁に頭をぶつけました。

16
Arthur Kovacs

私見私はこれを_$q.all_で行うための非常に巧妙な(そしてエレガントな)方法があると思います。

以下のコードをご覧ください。

私は、すべての結果を大きな配列に集約して、一度にデータを返すことを想定しています。

_var myApp = angular.module('myApp', []);

myApp.factory('myService', function ($http, $q) {
    return {
        getAllData: function () {
            return $q.all([
                $http.get('../wordpress/api/core/get_category_posts/?category_id=14'),
                $http.get('../wordpress/api/core/get_category_posts/?category_id=15'),
                $http.get('../wordpress/api/core/get_category_posts/?category_id=16'),
                $http.get('../wordpress/api/core/get_category_posts/?category_id=17')
            ]).then(function (results) {
                var aggregatedData = [];
                angular.forEach(results, function (result) {
                    aggregatedData = aggregatedData.concat(result.data);
                });
                return aggregatedData;
            });
        }
    };
});
_

上記を見ると、aggregatedDataが生成されるのは、_$q.all_を介してすべての非同期呼び出しが完了した場合に限られます。

たとえば、サービスを依存関係としてコントローラーの1つに含め、このようにサービスを呼び出すだけですmyService.getAllData()

完全に機能する例が必要であり、私がそれを提供できる場合は、それが役に立てば幸いです。 :)

60
Denison Luz

$http.get呼び出しは非同期ですが、延期を解決する前にそれらがすべて完了するまで待機していません。ここでは、コールが1秒以内に完了する時間がラッキーだからといって、タイムアウトで動作しますが、これはまったく信頼できません。

ここでは完全な解決策を繰り返し説明しませんが、別の同様の問題について my answer を確認します。

11
plalx