2016-06-28 18 views
2

私のカスタムサービスが動作するのに問題があります。サービス間で非同期にデータを取得/設定するコントローラ間でデータを共有する - AngularJS

次のように私のサービスは次のとおりです。

app.service('userService', function(){ 
    var user = []; 

    var setUser = function(newObj){ 
    user.push(newObj); 
    }; 

    var getUser = function(){ 
    return user; 
    }; 

    return { 
    setUser: setUser, 
    getUser: getUser 
    }; 
}); 

app.config(function($routeProvider,$locationProvider) { 

    $routeProvider 
    .when('/', { 
     templateUrl : 'views/home.html', 
     controller : 'indexController' 
    }) 
    .when('/me.html', { 
     templateUrl : 'views/me.html', 
     controller : 'meController' 
    }); 

    // Get rid of the additional default pound sign during routing 
    $locationProvider.html5Mode(true); 
}); 

app.controller('indexController', function($http,userService) { 
           ... 
    $http.post("somewhere") 
     .then(function(response){ 
      userService.setUser({test: "test}); 
      location="/me.html"; 
     } 
     .then(function(response){ 
      userService.setUser({test: "test}); 
      location="/me.html"; 
     }) 
}); 

私は別のコントローラではconsole.logを行うと、それは空の配列を返しますが、次のように私はそれを呼び出します。何がうんざりですか?私のコードのいくつかは曖昧だった

app.controller('meController',function($http,userService){ 
    console.log(userService.getUser()); => returns an empty array [] 

}); 

EDIT は、もう少し明確にする必要があり、私のルートセクションを追加しました。 EDIT 2 setUser()の後、console.log(userService.getUser())の行にスティックを置くと、正しくデータが表示されます。

すなわち多分

$http.post("somewhere") 
    .then(function(response){ 
     userService.setUser({test: "test}); 
     location="/me.html"; 
    } 
    .then(function(response){ 
     userService.setUser({test: "test}); 
     location="/me.html"; 
     console.log(userService.getUser()); => correct output 
    }) 
+0

コードに構文エラーがあります。 AJAXリクエストが完了した後、2番目のコントローラがデータを要求していることを確認していますか?コントローラが初期化されたときに表示される[mcve]を共有してください。 –

+1

'console.log'は、コントローラが作成されたときに実行され、アプリケーションが実行されるときに実行されます。その時点で配列には何もありません。あなたのアプリはうまくいくかもしれませんが、アレイに正しくアクセスしていないだけです。 –

+0

Hmm私は角度ルーティングを使用していますが、2番目のコントローラが後でインスタンス化されるという意味ではありませんか?コントローラが作成されたときには – intrinsiciwnl

答えて

0

console.log命令は、他のコントローラからデ逢引前に実行されるからです。

あなたはでそれを修正することができます:

$サービス
  • での約束は$broadcast/$emit
  • と信号システムを実装する実装 service.getUser()
  • をscope.watching
  • コールバックシステムを実装
    1. ケース1の場合、次のようにすることができます。

      app.service('userService', function(){ 
          var user = [],callbacks = []; 
      
          var setUser = function(newObj){ 
          user.push(newObj); 
          for(var i = 0;i< callbacks.length;++i) 
           callbacks[i](user); 
          }; 
      
          var getUser = function(){ 
          return user; 
          }; 
      
          var onUserChange = function(callback) { 
          callbacks.push(callback); 
          }; 
      
          return {  
          onUserChange:onUserChange, 
          setUser: setUser, 
          getUser: getUser 
          }; 
      }); 
      

      とし、2番目のコントローラで呼び出してみます。ケース2の場合

      app.controller('meController',function($http,$scope,userService){ 
          $scope.$watch(function(){ return userService.getUser(); }, 
             function(newvalue){ console.log(newvalue); }, 
             true); 
      
      }); 
      
  • +0

    いいえ3はそれを行う正しい方法です... –

    +0

    それは異なります。非常に大規模なWebアプリケーションでは、$ダイジェストサイクルを短くしてアプリケーションを高速に保つために、すべてを見るのはお勧めしません。最も一般的なのは、コントローラからサービスへの変更を見ること、または '$ broadcast' /' $ emit'を使ってシグナルシステムを実装することです。 – morels

    +0

    私は約束を実装していません。 –

    0

    は私のプロジェクトのために私は通常、それぞれのサービスで私$http秒のすべてを入れて、それが外に呼び出される必要がある場合には機能を公開します。

    app.service('userService', function(){ 
        var user = []; 
        var isReady = false; 
    
        var setUser = function(newObj){ 
        user.push(newObj); 
    
        $http(...).then(function(){}, failHandler); 
    
        function failHandler() { 
         // undo the push and show error to user 
        } 
        }; 
    
        var getUser = function(){ 
        if (isReady) { 
         return $q.when(user); 
        } 
        else { 
         return $http(...).then(function(data){ 
         user = data.xxx; 
         isReady = true; 
         }); 
        } 
        }; 
    
        return { 
        setUser: setUser, 
        getUser: getUser 
        }; 
    }); 
    

    getUserは今の約束を返しているので、あなたが物事を処理するために.thenを使用する必要があります。

    コントローラー側で成功またはエラーを表示するために、setUserを変更することもできます。

    関連する問題