2016-08-12 8 views
1

サービスの戻り値を変数に代入できないという問題があります。私は2つのコントローラ(AddProjectとEditProject)を持っており、この関数は両方にあったので、コードを繰り返さないようにするサービスを作りたかったのです。プロミス内のデータを操作してサービス関数で返す - AngularJS

 ... 
     .service("UserService", function($http) { 
     var allUsers; 
     var usersPromise = $http.get("/users"); 
     usersPromise.then(
      function(response) { 
       allUsers = response.data.map(function(user) { 
        user._lowername = user.name.toLowerCase(); 
        return user; 
       }); 
       console.log(allUsers) //It prints the object array 
       return allUsers; 
      }, 
      function(error) { 
       console.log(error); 
       return error; 
      }); 

     this.AllUsers = function() { 
      return allUsers; 
     } 
    }) 

そして、私のコントローラで私は、変数を持っている: (必要なすべての注射が行われたと仮定)

self.AllUsers = UserService.AllUsers(); //it is undefined 

私は$ Qを使用しようとしたが、それはあまりにも未定義ます。

+0

?この任務の前にサービス約束が解決されたことは確かですか? – Ryan27

+0

約束をコントローラに直接返すことはできません、彼らは解決を処理することができますか? – noKid

+0

メソッドを呼び出すと、 'var allUsers'は' undefined'ですから!あなたは約束を返すべきです。 – estus

答えて

2

約束を使用する主な理由は、あなたが$ http.get()のような非同期呼び出しを処理することですが、あなたは同期的な方法でそれを使用しようとしているようです。あなたのサービスは、ちょうど、あなたのコントローラーはそれを呼び出すと、それが解決したときに必要なものを行う必要があり、約束を返す必要があります:

.service("UserService", function($http) { 
    var allUsers; 
    var usersPromise = $http.get("/users"); 
    usersPromise.then(
      function(response) { 
       allUsers = response.data.map(function(user) { 
        user._lowername = user.name.toLowerCase(); 
        return user; 
       }); 
       console.log(allUsers) //It prints the object array 
       return allUsers; 
      }, 
      function(error) { 
       console.log(error); 
       return error; 
      }); 

    this.AllUsers = function() { 
     return usersPromise; 
    }; 
}); 

....

UserService.AllUsers().then(function(users) { 
    self.AllUsers = users; 
}); 
+0

このようにすると、AllUsers()のすべての呼び出しが新しいサーバー呼び出しを実行するという問題があります。この質問に基づいて、OPは一度その電話をしたかったようです。 – mcgraphix

1

自己充填を戻すことができます後の値で充填される非同期関数から配列:それを充填する際

... 
    .service("UserService", function($http) { 
    var allUsers = []; 
    var usersPromise = $http.get("/users"); 
    usersPromise.then(
     function(response) { 
      var result = response.data.map(function(user) { 
       user._lowername = user.name.toLowerCase(); 
       return user; 
      }); 
      angular.copy(allUsers, result); 
     }, 
     function(error) { 
      console.log(error); 
      return error; 
     }); 

    this.AllUsers = function() { 
     return allUsers; 
    } 
}) 

angular.copyは配列への参照を変更しない、返された空の配列は、自動更新されますマチュアな視点で

このトリックは、特にngResource $resourceで使用されます。

+0

これを確認します。 –

0

部分的な解決策(私は最良の解決策があると信じています)。

.service("UserService", function($http) { 
    this.AllUsers = function() { 
     return $http.get("/users"); 
    } 
}) 

そして、私は、コントローラの外に機能を作成しました:

function mapUsers(userResponse){ 
    return userResponse.data.map(function(user) { 
     user._lowername = user.name.toLowerCase(); 
     return user; 
    }); 
} 

そして、私はこれを呼び出し、両方のコントローラで:

UserService.AllUsers().then(function(response) { 
      self.AllUsers = mapUsers(response); 
     }); 
このコントローラの割り当てが起こっている
+1

'mapUsers'ヘルパー関数は実際には良くありません。それは 'UserService'の仕事です。それはデータとそれを操作する責任であり、MVCモデルのように考えることができます。マップされたユーザー配列とマッピングされていないユーザー配列の両方がアプリで使用されている場合は、1つではなく2つのメソッドにします。 – estus

+1

私はestusに同意します。このように、 'UserService.allUsers()'を呼び出すすべてのコードは、何がその背後にあるのかを知る必要があり、 'mapUsers()'を適用して結果をフォーマットする必要があります。 'return $ http.get("/users ")。then(response => response.data.map(user =>(user._lowername = user.name.toLowerCase()、user) )) '元の試みと比較して今変更されたのは、呼び出し元のコードが' allUsers'の代わりに 'Promise 'を受け取ることだけです – Thomas

+0

本当にうまくいってくれてありがとう@Thomas! –

関連する問題