9

$httpJSON ファイルの 1 つを取得し、すべてのコントローラーでデータを使用するための単一の要求を作成しようとしています。

複数のコントローラー間でデータを共有する方法をegghead.ioで見ました。また、このStackOverflowの質問「angular.jsでコントローラー間で変数を共有する」も読みました。

$httpただし、そこの回答ではモジュールを使用していません。を使用している場合$http、コントローラーには処理するデータがなく、応答を受信するまでには既に手遅れです。

次に、StackOverflow でメソッド$q.deferとこの質問を見つけました:「AngularJS はコントローラー間で非同期サービス データを共有します

そこに投稿されたソリューションは正常に機能しますが、2 つの問題があります。

  1. $http各コントローラーは、別のコントローラーで既に使用されている同じデータを取得する要求をトリガーします。と、
  2. 受信したデータを操作しようとすると、then機能があります。

以下に私のコードを示します。

controllers.js

'use strict';

/* Controllers */

function appInstallerListCtrl($scope, Data) {
  $scope.apps = Data;
}

function appInstallerDetailCtrl($scope, $routeParams, Data) {
  $scope.appId = $routeParams.appId;
  $scope.apps = Data;  
  console.log($scope.apps); // <-- then function
  console.log(Data); // <-- then function with $vv data returned but I can't access it

  for (var i in $scope.apps) // <--- no way, baby!
    console.log(i);
}

app.js

var app = angular.module('appInstaller', []);

app.factory('Data', function($http, $q) {
  var defer = $q.defer();
  $http.get('apps.json').then(function(result) {
    defer.resolve(result.data.versions.version);
  });
  return defer.promise;
});

app.config(['$routeProvider', function($routeProvider) {
  $routeProvider.
    when('/app', {templateUrl: 'partials/app-list.html',   controller: appInstallerListCtrl}).
    when('/app/:appId', {templateUrl: 'partials/app-detail.html', controller: appInstallerDetailCtrl}).
    otherwise({redirectTo: '/app'});
}]);

私が望んでいるのは、アプリを起動すると、$httpリクエストが実行され、レスポンスがすべてのコントローラーでアプリ全体で使用されることです。

ありがとう

4

4 に答える 4

1

promise を使用しているため、promise によって返されたデータにアクセスするには、コールバック構文を使用します

function appInstallerDetailCtrl($scope, $routeParams, Data) {
  $scope.appId = $routeParams.appId;
   Data.then(function(returnedData) {
        $scope.apps=returnedData;
        console.log($scope.apps);
        for (var i in $scope.apps)
           console.log(i)   
   });   
}

これを確認してください

defer.resolve(result.data.versions.version);

上記のコードが機能するために、解決は配列を返します。または、データの内容を確認し、コントローラー コードを調整します。

于 2013-08-22T10:12:39.360 に答える
1

それが最善の方法であるかどうかわからない方法を見つけました。

HTMLで

<body ng-app="myApp">
  <div ng-controller="ctrl">{{user.title}}</div>
  <hr>
  <div ng-controller="ctrl2">{{user.title}}</div>
</body>

JavaScriptで

 var app = angular.module('myApp', []);
   app.controller('ctrl', function($scope, $http, userService) {
      userService.getUser().then(function(user) {
        $scope.user = user;
      });
    });

   app.controller('ctrl2', function($scope, $http, userService) {
      userService.getUser().then(function(user) {
        $scope.user = user;
      });
    });

   app.factory('userService', function($http, $q) {
    var promise;
    var deferred = $q.defer();
      return {
        getUser: function() {
          if(!promise){     
          promise = $http({
              method: "GET",
              url: "https://jsonplaceholder.typicode.com/posts/1"
            }).success(function(res) {
                data = res.data;
              deferred.resolve(res);
            })
            .error(function(err, status) {
              deferred.reject(err)
            });
          return deferred.promise;
          }
          return deferred.promise;
        }
      }
    });

これにより、正確に 1 つの HTTP リクエストのみが作成されます。

于 2016-09-21T13:38:04.873 に答える
0

resolve私の問題は、ネットワークが遅い場合にコントローラー間に「ラグ」が表示されるため、別のコントローラーをロードする前に待機したくないことでした。私の実用的なソリューションは、 を介してコントローラー間で promise を渡すことであり、 promiseからui-routerparamsデータは、次のように 2 番目のコントローラーに非同期的にロードできます。

app.route.js - 検索結果を表示する SearchController に渡される利用可能なパラメーターを設定します。

        .state('search', {
            url: '/search',
            templateUrl: baseDir + 'search/templates/index.html',
            controller: 'SearchController',
            params: {
                searchPromise: null
            }
        })

landing.controller.js - ユーザーが検索入力を追加して送信するコントローラー

    let promise = SearchService.search(form);
    $state.go('search', {
        searchPromise: promise
    });

search.service.js - ユーザー入力から promise を返すサービス

    function search(params) {
        return new Promise(function (resolve, reject) {
            $timeout(function() {
                resolve([]) // mimic a slow query but illustrates a point
            }, 3000)
        })
    }

search.controller.js - 検索コントローラー

    let promise = $state.params.searchPromise;

    promise.then(r => {
        console.log('search result',r);
    })
于 2017-01-17T10:01:01.627 に答える